mirror of
https://github.com/qpdf/qpdf.git
synced 2025-01-02 22:50:20 +00:00
Add QPDFObjectHandle::shallowCopy()
This commit is contained in:
parent
9689f4cdcf
commit
d1ebe30ff6
@ -1,5 +1,7 @@
|
||||
2012-06-21 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* QPDFObjectHandle: add shallowCopy() method
|
||||
|
||||
* QPDF: add new APIs for adding and removing pages. This includes
|
||||
addPage(), addPageAt(), and removePage(). Also a method
|
||||
updateAllPagesCache() is now available to force update of the
|
||||
|
@ -190,6 +190,13 @@ class QPDFObjectHandle
|
||||
QPDF_DLL
|
||||
bool isOrHasName(std::string const&);
|
||||
|
||||
// Create a shallow copy of an object as a direct object. Since
|
||||
// this is a shallow copy, for dictionaries and arrays, any keys
|
||||
// or items that were indirect objects will still be indirect
|
||||
// objects that point to the same place.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle shallowCopy();
|
||||
|
||||
// Mutator methods. Use with caution.
|
||||
|
||||
// Recursively copy this object, making it direct. Throws an
|
||||
|
@ -663,6 +663,38 @@ QPDFObjectHandle::newStream(QPDF* qpdf, PointerHolder<Buffer> data)
|
||||
return result;
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDFObjectHandle::shallowCopy()
|
||||
{
|
||||
assertInitialized();
|
||||
|
||||
if (isStream())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle ERR shallow copy stream");
|
||||
throw std::runtime_error(
|
||||
"attempt to make a shallow copy of a stream");
|
||||
}
|
||||
|
||||
QPDFObjectHandle new_obj;
|
||||
if (isArray())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle shallow copy array");
|
||||
new_obj = newArray(getArrayAsVector());
|
||||
}
|
||||
else if (isDictionary())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle shallow copy dictionary");
|
||||
new_obj = newDictionary(getDictAsMap());
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle shallow copy scalar");
|
||||
new_obj = *this;
|
||||
}
|
||||
|
||||
return new_obj;
|
||||
}
|
||||
|
||||
void
|
||||
QPDFObjectHandle::makeDirectInternal(std::set<int>& visited)
|
||||
{
|
||||
|
@ -209,3 +209,7 @@ QPDF insert page 2
|
||||
QPDF updateAllPagesCache 0
|
||||
QPDF insert non-indirect page 0
|
||||
QPDF insert indirect page 0
|
||||
QPDFObjectHandle ERR shallow copy stream 0
|
||||
QPDFObjectHandle shallow copy array 0
|
||||
QPDFObjectHandle shallow copy dictionary 0
|
||||
QPDFObjectHandle shallow copy scalar 0
|
||||
|
@ -144,7 +144,7 @@ $td->runtest("duplicate page",
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
# ----------
|
||||
$td->notify("--- Miscellaneous Tests ---");
|
||||
$n_tests += 37;
|
||||
$n_tests += 40;
|
||||
|
||||
$td->runtest("qpdf version",
|
||||
{$td->COMMAND => "qpdf --version"},
|
||||
@ -338,6 +338,18 @@ $td->runtest("check output",
|
||||
{$td->FILE => "c-info-out.pdf"});
|
||||
unlink "a.pdf" or die;
|
||||
|
||||
$td->runtest("shallow copy an array",
|
||||
{$td->COMMAND => "test_driver 20 shallow_array.pdf"},
|
||||
{$td->STRING => "test 20 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "shallow_array-out.pdf"});
|
||||
$td->runtest("shallow copy a stream",
|
||||
{$td->COMMAND => "test_driver 21 shallow_array.pdf"},
|
||||
{$td->FILE => "shallow_stream.out", $td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
$td->notify("--- Error Condition Tests ---");
|
||||
|
40
qpdf/qtest/qpdf/shallow_array-out.pdf
Normal file
40
qpdf/qtest/qpdf/shallow_array-out.pdf
Normal file
@ -0,0 +1,40 @@
|
||||
%PDF-1.3
|
||||
%¿÷¢þ
|
||||
1 0 obj
|
||||
<< /Pages 2 0 R /Type /Catalog >>
|
||||
endobj
|
||||
2 0 obj
|
||||
<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >>
|
||||
endobj
|
||||
3 0 obj
|
||||
<< /Contents 4 0 R /MediaBox [ 0 0 612 792 ] /Parent 2 0 R /Resources << /Font << /F1 5 0 R >> /ProcSet 6 0 R >> /Type /Page >>
|
||||
endobj
|
||||
4 0 obj
|
||||
<< /Length 44 >>
|
||||
stream
|
||||
BT
|
||||
/F1 24 Tf
|
||||
72 720 Td
|
||||
(Potato) Tj
|
||||
ET
|
||||
endstream
|
||||
endobj
|
||||
5 0 obj
|
||||
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
|
||||
endobj
|
||||
6 0 obj
|
||||
[ /PDF /Text ]
|
||||
endobj
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000015 00000 n
|
||||
0000000064 00000 n
|
||||
0000000123 00000 n
|
||||
0000000266 00000 n
|
||||
0000000359 00000 n
|
||||
0000000466 00000 n
|
||||
trailer << /QTest [ /A 1 0 R /B ] /QTest2 [ /A 1 0 R /B 7 ] /Root 1 0 R /Size 7 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >>
|
||||
startxref
|
||||
496
|
||||
%%EOF
|
80
qpdf/qtest/qpdf/shallow_array.pdf
Normal file
80
qpdf/qtest/qpdf/shallow_array.pdf
Normal file
@ -0,0 +1,80 @@
|
||||
%PDF-1.3
|
||||
1 0 obj
|
||||
<<
|
||||
/Type /Catalog
|
||||
/Pages 2 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<<
|
||||
/Type /Pages
|
||||
/Kids [
|
||||
3 0 R
|
||||
]
|
||||
/Count 1
|
||||
>>
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<<
|
||||
/Type /Page
|
||||
/Parent 2 0 R
|
||||
/MediaBox [0 0 612 792]
|
||||
/Contents 4 0 R
|
||||
/Resources <<
|
||||
/ProcSet 5 0 R
|
||||
/Font <<
|
||||
/F1 6 0 R
|
||||
>>
|
||||
>>
|
||||
>>
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<<
|
||||
/Length 44
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
/F1 24 Tf
|
||||
72 720 Td
|
||||
(Potato) Tj
|
||||
ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
]
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<<
|
||||
/Type /Font
|
||||
/Subtype /Type1
|
||||
/Name /F1
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000009 00000 n
|
||||
0000000063 00000 n
|
||||
0000000135 00000 n
|
||||
0000000307 00000 n
|
||||
0000000403 00000 n
|
||||
0000000438 00000 n
|
||||
trailer <<
|
||||
/Size 7
|
||||
/Root 1 0 R
|
||||
/QTest [ /A 1 0 R /B ]
|
||||
>>
|
||||
startxref
|
||||
556
|
||||
%%EOF
|
1
qpdf/qtest/qpdf/shallow_stream.out
Normal file
1
qpdf/qtest/qpdf/shallow_stream.out
Normal file
@ -0,0 +1 @@
|
||||
attempt to make a shallow copy of a stream
|
@ -691,17 +691,15 @@ void runtest(int n, char const* filename)
|
||||
// dictionary and modify it. Using the results of
|
||||
// getDictAsMap to create a new dictionary effectively creates
|
||||
// a shallow copy.
|
||||
std::map<std::string, QPDFObjectHandle> page_dict_keys =
|
||||
QPDFObjectHandle(pages[0]).getDictAsMap();
|
||||
QPDFObjectHandle page_tempate = pages[0];
|
||||
std::vector<QPDFObjectHandle> new_pages;
|
||||
for (std::vector<QPDFObjectHandle>::iterator iter = contents.begin();
|
||||
iter != contents.end(); ++iter)
|
||||
{
|
||||
// We will retain indirect object references to other
|
||||
// indirect objects other than page content.
|
||||
page_dict_keys["/Contents"] = *iter;
|
||||
QPDFObjectHandle page =
|
||||
QPDFObjectHandle::newDictionary(page_dict_keys);
|
||||
QPDFObjectHandle page = page_tempate.shallowCopy();
|
||||
page.replaceKey("/Contents", *iter);
|
||||
if (iter == contents.begin())
|
||||
{
|
||||
// leave direct
|
||||
@ -745,12 +743,10 @@ void runtest(int n, char const* filename)
|
||||
std::vector<QPDFObjectHandle> const& all_pages = pdf.getAllPages();
|
||||
|
||||
QPDFObjectHandle contents = createPageContents(pdf, "New page 10");
|
||||
std::map<std::string, QPDFObjectHandle> page_dict_keys =
|
||||
QPDFObjectHandle(all_pages[0]).getDictAsMap();
|
||||
page_dict_keys["/Contents"] = contents;
|
||||
QPDFObjectHandle page =
|
||||
pdf.makeIndirectObject(
|
||||
QPDFObjectHandle::newDictionary(page_dict_keys));
|
||||
QPDFObjectHandle(all_pages[0]).shallowCopy());
|
||||
page.replaceKey("/Contents", contents);
|
||||
|
||||
// Insert the page manually.
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
@ -807,6 +803,30 @@ void runtest(int n, char const* filename)
|
||||
pdf.addPage(pages[5], false);
|
||||
std::cout << "you can't see this" << std::endl;
|
||||
}
|
||||
else if (n == 20)
|
||||
{
|
||||
// Shallow copy an array
|
||||
QPDFObjectHandle trailer = pdf.getTrailer();
|
||||
QPDFObjectHandle qtest = trailer.getKey("/QTest");
|
||||
QPDFObjectHandle copy = qtest.shallowCopy();
|
||||
// Append shallow copy of a scalar
|
||||
copy.appendItem(trailer.getKey("/Size").shallowCopy());
|
||||
trailer.replaceKey("/QTest2", copy);
|
||||
|
||||
QPDFWriter w(pdf, "a.pdf");
|
||||
w.setStaticID(true);
|
||||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 21)
|
||||
{
|
||||
// Try to shallow copy a stream
|
||||
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
|
||||
QPDFObjectHandle page = pages[0];
|
||||
QPDFObjectHandle contents = page.getKey("/Contents");
|
||||
contents.shallowCopy();
|
||||
std::cout << "you can't see this" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(std::string("invalid test ") +
|
||||
|
Loading…
Reference in New Issue
Block a user