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>
|
2012-06-21 Jay Berkenbilt <ejb@ql.org>
|
||||||
|
|
||||||
|
* QPDFObjectHandle: add shallowCopy() method
|
||||||
|
|
||||||
* QPDF: add new APIs for adding and removing pages. This includes
|
* QPDF: add new APIs for adding and removing pages. This includes
|
||||||
addPage(), addPageAt(), and removePage(). Also a method
|
addPage(), addPageAt(), and removePage(). Also a method
|
||||||
updateAllPagesCache() is now available to force update of the
|
updateAllPagesCache() is now available to force update of the
|
||||||
|
@ -190,6 +190,13 @@ class QPDFObjectHandle
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool isOrHasName(std::string const&);
|
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.
|
// Mutator methods. Use with caution.
|
||||||
|
|
||||||
// Recursively copy this object, making it direct. Throws an
|
// Recursively copy this object, making it direct. Throws an
|
||||||
|
@ -663,6 +663,38 @@ QPDFObjectHandle::newStream(QPDF* qpdf, PointerHolder<Buffer> data)
|
|||||||
return result;
|
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
|
void
|
||||||
QPDFObjectHandle::makeDirectInternal(std::set<int>& visited)
|
QPDFObjectHandle::makeDirectInternal(std::set<int>& visited)
|
||||||
{
|
{
|
||||||
|
@ -209,3 +209,7 @@ QPDF insert page 2
|
|||||||
QPDF updateAllPagesCache 0
|
QPDF updateAllPagesCache 0
|
||||||
QPDF insert non-indirect page 0
|
QPDF insert non-indirect page 0
|
||||||
QPDF insert 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->NORMALIZE_NEWLINES);
|
||||||
# ----------
|
# ----------
|
||||||
$td->notify("--- Miscellaneous Tests ---");
|
$td->notify("--- Miscellaneous Tests ---");
|
||||||
$n_tests += 37;
|
$n_tests += 40;
|
||||||
|
|
||||||
$td->runtest("qpdf version",
|
$td->runtest("qpdf version",
|
||||||
{$td->COMMAND => "qpdf --version"},
|
{$td->COMMAND => "qpdf --version"},
|
||||||
@ -338,6 +338,18 @@ $td->runtest("check output",
|
|||||||
{$td->FILE => "c-info-out.pdf"});
|
{$td->FILE => "c-info-out.pdf"});
|
||||||
unlink "a.pdf" or die;
|
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();
|
show_ntests();
|
||||||
# ----------
|
# ----------
|
||||||
$td->notify("--- Error Condition Tests ---");
|
$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
|
// dictionary and modify it. Using the results of
|
||||||
// getDictAsMap to create a new dictionary effectively creates
|
// getDictAsMap to create a new dictionary effectively creates
|
||||||
// a shallow copy.
|
// a shallow copy.
|
||||||
std::map<std::string, QPDFObjectHandle> page_dict_keys =
|
QPDFObjectHandle page_tempate = pages[0];
|
||||||
QPDFObjectHandle(pages[0]).getDictAsMap();
|
|
||||||
std::vector<QPDFObjectHandle> new_pages;
|
std::vector<QPDFObjectHandle> new_pages;
|
||||||
for (std::vector<QPDFObjectHandle>::iterator iter = contents.begin();
|
for (std::vector<QPDFObjectHandle>::iterator iter = contents.begin();
|
||||||
iter != contents.end(); ++iter)
|
iter != contents.end(); ++iter)
|
||||||
{
|
{
|
||||||
// We will retain indirect object references to other
|
// We will retain indirect object references to other
|
||||||
// indirect objects other than page content.
|
// indirect objects other than page content.
|
||||||
page_dict_keys["/Contents"] = *iter;
|
QPDFObjectHandle page = page_tempate.shallowCopy();
|
||||||
QPDFObjectHandle page =
|
page.replaceKey("/Contents", *iter);
|
||||||
QPDFObjectHandle::newDictionary(page_dict_keys);
|
|
||||||
if (iter == contents.begin())
|
if (iter == contents.begin())
|
||||||
{
|
{
|
||||||
// leave direct
|
// leave direct
|
||||||
@ -745,12 +743,10 @@ void runtest(int n, char const* filename)
|
|||||||
std::vector<QPDFObjectHandle> const& all_pages = pdf.getAllPages();
|
std::vector<QPDFObjectHandle> const& all_pages = pdf.getAllPages();
|
||||||
|
|
||||||
QPDFObjectHandle contents = createPageContents(pdf, "New page 10");
|
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 =
|
QPDFObjectHandle page =
|
||||||
pdf.makeIndirectObject(
|
pdf.makeIndirectObject(
|
||||||
QPDFObjectHandle::newDictionary(page_dict_keys));
|
QPDFObjectHandle(all_pages[0]).shallowCopy());
|
||||||
|
page.replaceKey("/Contents", contents);
|
||||||
|
|
||||||
// Insert the page manually.
|
// Insert the page manually.
|
||||||
QPDFObjectHandle root = pdf.getRoot();
|
QPDFObjectHandle root = pdf.getRoot();
|
||||||
@ -807,6 +803,30 @@ void runtest(int n, char const* filename)
|
|||||||
pdf.addPage(pages[5], false);
|
pdf.addPage(pages[5], false);
|
||||||
std::cout << "you can't see this" << std::endl;
|
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
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error(std::string("invalid test ") +
|
throw std::runtime_error(std::string("invalid test ") +
|
||||||
|
Loading…
Reference in New Issue
Block a user