Commit cee2592ed1f1c8ac5ca3048c48ac082e47358a6b

Authored by Jay Berkenbilt
1 parent f31e526d

Change API/ABI and withdraw 4.2.0

4.2.0 was binary incompatible in spite of there being no deletions or
changes to any public methods.  As such, we have to bump the ABI and
are fixing some API breakage while we're at it.

Previous 4.3.0 target is now 5.1.0.
ChangeLog
  1 +2013-07-10 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * 4.2.0 turned out to be binary incompatible on some platforms
  4 + even though there were no changes to the public API. Therefore
  5 + the 4.2.0 release has been withdrawn, and is being replaced with a
  6 + 5.0.0 release that acknowledges the ABI change and also removes
  7 + some problematic methods from the public API.
  8 +
  9 + * Remove methods from public API that were only intended to be
  10 + used by QPDFWriter and really didn't make sense to call from
  11 + anywhere else as they required internal knowledge that only
  12 + QPDFWriter had:
  13 + - QPDF::getLinearizedParts
  14 + - QPDF::generateHintStream
  15 + - QPDF::getObjectStreamData
  16 + - QPDF::getCompressibleObjGens
  17 + - QPDF::getCompressibleObjects
  18 +
1 2013-07-07 Jay Berkenbilt <ejb@ql.org> 19 2013-07-07 Jay Berkenbilt <ejb@ql.org>
2 20
3 - * 4.2.0: release 21 + * 4.2.0: release [withdrawn]
4 22
5 * Ignore error case of a stream's decode parameters having invalid 23 * Ignore error case of a stream's decode parameters having invalid
6 length when there are no stream filters. 24 length when there are no stream filters.
1 -4.3.0 1 +5.1.0
2 ===== 2 =====
3 3
  4 + * Figure out what about a3576a73593987b26cd3eff346f8f7c11f713cbd
  5 + broke binary compatibility.
  6 +
  7 + * Implement automated testing for binary compatibility and add to
  8 + release checklist.
  9 +
4 * Add method to push inheritable resources to a single page by 10 * Add method to push inheritable resources to a single page by
5 walking up and copying without overwrite. Above logic will also be 11 walking up and copying without overwrite. Above logic will also be
6 sufficient to fix the limitation in 12 sufficient to fix the limitation in
@@ -55,19 +61,6 @@ @@ -55,19 +61,6 @@
55 61
56 62
57 63
58 -Next ABI change  
59 -===============  
60 -  
61 - * Remove QPDF::getCompressibleObjects()  
62 -  
63 - * For public QPDF methods that are only public so QPDFWriter can  
64 - call them, make them private and provide a nested caller class with  
65 - QPDFWriter as a friend for access just like is being done now for  
66 - some other methods. This will reduce the risk that future changes  
67 - in the interface between QPDFWriter and QPDF will result in  
68 - breaking ABI changes.  
69 -  
70 -  
71 General 64 General
72 ======= 65 =======
73 66
include/qpdf/QPDF.hh
@@ -411,45 +411,6 @@ class QPDF @@ -411,45 +411,6 @@ class QPDF
411 void optimize(std::map<int, int> const& object_stream_data, 411 void optimize(std::map<int, int> const& object_stream_data,
412 bool allow_changes = true); 412 bool allow_changes = true);
413 413
414 - // For QPDFWriter:  
415 -  
416 - // Get lists of all objects in order according to the part of a  
417 - // linearized file that they belong to.  
418 - QPDF_DLL  
419 - void getLinearizedParts(  
420 - std::map<int, int> const& object_stream_data,  
421 - std::vector<QPDFObjectHandle>& part4,  
422 - std::vector<QPDFObjectHandle>& part6,  
423 - std::vector<QPDFObjectHandle>& part7,  
424 - std::vector<QPDFObjectHandle>& part8,  
425 - std::vector<QPDFObjectHandle>& part9);  
426 -  
427 - QPDF_DLL  
428 - void generateHintStream(std::map<int, QPDFXRefEntry> const& xref,  
429 - std::map<int, qpdf_offset_t> const& lengths,  
430 - std::map<int, int> const& obj_renumber,  
431 - PointerHolder<Buffer>& hint_stream,  
432 - int& S, int& O);  
433 -  
434 - // Map object to object stream that contains it  
435 - QPDF_DLL  
436 - void getObjectStreamData(std::map<int, int>&);  
437 -  
438 - // Get a list of objects that would be permitted in an object  
439 - // stream.  
440 - QPDF_DLL  
441 - std::vector<QPDFObjGen> getCompressibleObjGens();  
442 -  
443 - // Deprecated: get a list of objects that would be permitted in an  
444 - // object stream. This method is deprecated and will be removed.  
445 - // It's incorrect because it disregards the generations of the  
446 - // compressible objects, which can lead (and has lead) to bugs.  
447 - // This method will throw an exception if any of the objects  
448 - // returned have a generation of other than zero. Use  
449 - // getCompressibleObjGens() instead.  
450 - QPDF_DLL  
451 - std::vector<int> getCompressibleObjects();  
452 -  
453 // Convenience routines for common functions. See also 414 // Convenience routines for common functions. See also
454 // QPDFObjectHandle.hh for additional convenience routines. 415 // QPDFObjectHandle.hh for additional convenience routines.
455 416
@@ -504,6 +465,49 @@ class QPDF @@ -504,6 +465,49 @@ class QPDF
504 QPDF_DLL 465 QPDF_DLL
505 void removePage(QPDFObjectHandle page); 466 void removePage(QPDFObjectHandle page);
506 467
  468 + // Writer class is restricted to QPDFWriter so that only it can
  469 + // call certain methods.
  470 + class Writer
  471 + {
  472 + friend class QPDFWriter;
  473 + private:
  474 +
  475 + static void getLinearizedParts(
  476 + QPDF& qpdf,
  477 + std::map<int, int> const& object_stream_data,
  478 + std::vector<QPDFObjectHandle>& part4,
  479 + std::vector<QPDFObjectHandle>& part6,
  480 + std::vector<QPDFObjectHandle>& part7,
  481 + std::vector<QPDFObjectHandle>& part8,
  482 + std::vector<QPDFObjectHandle>& part9)
  483 + {
  484 + qpdf.getLinearizedParts(object_stream_data,
  485 + part4, part6, part7, part8, part9);
  486 + }
  487 +
  488 + static void generateHintStream(
  489 + QPDF& qpdf,
  490 + std::map<int, QPDFXRefEntry> const& xref,
  491 + std::map<int, qpdf_offset_t> const& lengths,
  492 + std::map<int, int> const& obj_renumber,
  493 + PointerHolder<Buffer>& hint_stream,
  494 + int& S, int& O)
  495 + {
  496 + return qpdf.generateHintStream(xref, lengths, obj_renumber,
  497 + hint_stream, S, O);
  498 + }
  499 +
  500 + static void getObjectStreamData(QPDF& qpdf, std::map<int, int>& omap)
  501 + {
  502 + qpdf.getObjectStreamData(omap);
  503 + }
  504 +
  505 + static std::vector<QPDFObjGen> getCompressibleObjGens(QPDF& qpdf)
  506 + {
  507 + return qpdf.getCompressibleObjGens();
  508 + }
  509 + };
  510 +
507 // Resolver class is restricted to QPDFObjectHandle so that only 511 // Resolver class is restricted to QPDFObjectHandle so that only
508 // it can resolve indirect references. 512 // it can resolve indirect references.
509 class Resolver 513 class Resolver
@@ -635,6 +639,31 @@ class QPDF @@ -635,6 +639,31 @@ class QPDF
635 QPDFObjectHandle dict, 639 QPDFObjectHandle dict,
636 Pipeline* pipeline); 640 Pipeline* pipeline);
637 641
  642 + // For QPDFWriter:
  643 +
  644 + // Get lists of all objects in order according to the part of a
  645 + // linearized file that they belong to.
  646 + void getLinearizedParts(
  647 + std::map<int, int> const& object_stream_data,
  648 + std::vector<QPDFObjectHandle>& part4,
  649 + std::vector<QPDFObjectHandle>& part6,
  650 + std::vector<QPDFObjectHandle>& part7,
  651 + std::vector<QPDFObjectHandle>& part8,
  652 + std::vector<QPDFObjectHandle>& part9);
  653 +
  654 + void generateHintStream(std::map<int, QPDFXRefEntry> const& xref,
  655 + std::map<int, qpdf_offset_t> const& lengths,
  656 + std::map<int, int> const& obj_renumber,
  657 + PointerHolder<Buffer>& hint_stream,
  658 + int& S, int& O);
  659 +
  660 + // Map object to object stream that contains it
  661 + void getObjectStreamData(std::map<int, int>&);
  662 +
  663 + // Get a list of objects that would be permitted in an object
  664 + // stream.
  665 + std::vector<QPDFObjGen> getCompressibleObjGens();
  666 +
638 // methods to support page handling 667 // methods to support page handling
639 668
640 void getAllPagesInternal(QPDFObjectHandle cur_pages, 669 void getAllPagesInternal(QPDFObjectHandle cur_pages,
libqpdf/QPDF.cc
@@ -1952,30 +1952,6 @@ QPDF::getObjectStreamData(std::map&lt;int, int&gt;&amp; omap) @@ -1952,30 +1952,6 @@ QPDF::getObjectStreamData(std::map&lt;int, int&gt;&amp; omap)
1952 } 1952 }
1953 } 1953 }
1954 1954
1955 -std::vector<int>  
1956 -QPDF::getCompressibleObjects()  
1957 -{  
1958 - std::vector<QPDFObjGen> objects = getCompressibleObjGens();  
1959 - std::vector<int> result;  
1960 - for (std::vector<QPDFObjGen>::iterator iter = objects.begin();  
1961 - iter != objects.end(); ++iter)  
1962 - {  
1963 - if ((*iter).getGen() != 0)  
1964 - {  
1965 - throw std::logic_error(  
1966 - "QPDF::getCompressibleObjects() would return an object ID"  
1967 - " for an object with generation != 0. Use"  
1968 - " QPDF::getCompressibleObjGens() instead."  
1969 - " See comments in QPDF.hh.");  
1970 - }  
1971 - else  
1972 - {  
1973 - result.push_back((*iter).getObj());  
1974 - }  
1975 - }  
1976 - return result;  
1977 -}  
1978 -  
1979 std::vector<QPDFObjGen> 1955 std::vector<QPDFObjGen>
1980 QPDF::getCompressibleObjGens() 1956 QPDF::getCompressibleObjGens()
1981 { 1957 {
libqpdf/QPDFWriter.cc
@@ -1913,7 +1913,7 @@ QPDFWriter::preserveObjectStreams() @@ -1913,7 +1913,7 @@ QPDFWriter::preserveObjectStreams()
1913 // must have generation 0 because the PDF spec does not provide 1913 // must have generation 0 because the PDF spec does not provide
1914 // any way to do otherwise. 1914 // any way to do otherwise.
1915 std::map<int, int> omap; 1915 std::map<int, int> omap;
1916 - this->pdf.getObjectStreamData(omap); 1916 + QPDF::Writer::getObjectStreamData(this->pdf, omap);
1917 for (std::map<int, int>::iterator iter = omap.begin(); 1917 for (std::map<int, int>::iterator iter = omap.begin();
1918 iter != omap.end(); ++iter) 1918 iter != omap.end(); ++iter)
1919 { 1919 {
@@ -1936,7 +1936,7 @@ QPDFWriter::generateObjectStreams() @@ -1936,7 +1936,7 @@ QPDFWriter::generateObjectStreams()
1936 // This code doesn't do anything with /Extends. 1936 // This code doesn't do anything with /Extends.
1937 1937
1938 std::vector<QPDFObjGen> const& eligible = 1938 std::vector<QPDFObjGen> const& eligible =
1939 - this->pdf.getCompressibleObjGens(); 1939 + QPDF::Writer::getCompressibleObjGens(this->pdf);
1940 unsigned int n_object_streams = (eligible.size() + 99) / 100; 1940 unsigned int n_object_streams = (eligible.size() + 99) / 100;
1941 unsigned int n_per = eligible.size() / n_object_streams; 1941 unsigned int n_per = eligible.size() / n_object_streams;
1942 if (n_per * n_object_streams < eligible.size()) 1942 if (n_per * n_object_streams < eligible.size())
@@ -2339,8 +2339,8 @@ QPDFWriter::writeHintStream(int hint_id) @@ -2339,8 +2339,8 @@ QPDFWriter::writeHintStream(int hint_id)
2339 PointerHolder<Buffer> hint_buffer; 2339 PointerHolder<Buffer> hint_buffer;
2340 int S = 0; 2340 int S = 0;
2341 int O = 0; 2341 int O = 0;
2342 - pdf.generateHintStream(  
2343 - this->xref, this->lengths, this->obj_renumber_no_gen, 2342 + QPDF::Writer::generateHintStream(
  2343 + this->pdf, this->xref, this->lengths, this->obj_renumber_no_gen,
2344 hint_buffer, S, O); 2344 hint_buffer, S, O);
2345 2345
2346 openObject(hint_id); 2346 openObject(hint_id);
@@ -2610,8 +2610,9 @@ QPDFWriter::writeLinearized() @@ -2610,8 +2610,9 @@ QPDFWriter::writeLinearized()
2610 std::vector<QPDFObjectHandle> part7; 2610 std::vector<QPDFObjectHandle> part7;
2611 std::vector<QPDFObjectHandle> part8; 2611 std::vector<QPDFObjectHandle> part8;
2612 std::vector<QPDFObjectHandle> part9; 2612 std::vector<QPDFObjectHandle> part9;
2613 - pdf.getLinearizedParts(this->object_to_object_stream_no_gen,  
2614 - part4, part6, part7, part8, part9); 2613 + QPDF::Writer::getLinearizedParts(
  2614 + this->pdf, this->object_to_object_stream_no_gen,
  2615 + part4, part6, part7, part8, part9);
2615 2616
2616 // Object number sequence: 2617 // Object number sequence:
2617 // 2618 //