C API: add functions for working with pages (fixes #594)

This commit is contained in:
Jay Berkenbilt 2021-12-16 14:36:21 -05:00
parent f072be032f
commit 9bb6f570ec
9 changed files with 955 additions and 1 deletions

View File

@ -1,3 +1,10 @@
2021-12-16 Jay Berkenbilt <ejb@ql.org>
* Add several functions to the C API for working with pages. C
wrappers around sevearl of the "Legacy" page operations from
QPDFObjectHandle.hh have been added. See "PAGE FUNCTIONS" in
qpdf-c.h for details. Fixes #594.
2021-12-12 Jay Berkenbilt <ejb@ql.org>
* Convert documentation from docbook to reStructuredText/Sphinx.

View File

@ -788,6 +788,67 @@ extern "C" {
char const* qpdf_oh_unparse_resolved(qpdf_data qpdf, qpdf_oh oh);
QPDF_DLL
char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh);
/* PAGE FUNCTIONS */
/* The first time a page function is called, qpdf will traverse
* the /Pages tree. Subsequent calls to retrieve the number of
* pages or a specific page run in constant time as they are
* accessing the pages cache. If you manipulate the page tree
* outside of these functions, you should call
* qpdf_update_all_pages_cache. See comments for getAllPages() and
* updateAllPagesCache() in QPDF.hh.
*/
/* For each function, the corresponding method in QPDF.hh is
* referenced. Please see comments in QPDF.hh for details.
*/
/* calls getAllPages(). On error, returns -1 and sets error for
* qpdf_get_error. */
QPDF_DLL
int qpdf_get_num_pages(qpdf_data qpdf);
/* returns uninitialized object if out of range */
QPDF_DLL
qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t zero_based_index);
/* updateAllPagesCache() */
QPDF_DLL
QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf);
/* findPage() -- return zero-based index. If page is not found,
* return -1 and save the error to be retrieved with
* qpdf_get_error.
*/
QPDF_DLL
int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation);
QPDF_DLL
int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh);
/* pushInheritedAttributesToPage() */
QPDF_DLL
QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf);
/* Functions that add pages may add pages from other files. If
* adding a page from the same file, newpage_qpdf and qpdf are the
* same.
/*/
/* addPage() */
QPDF_DLL
QPDF_ERROR_CODE qpdf_add_page(
qpdf_data qpdf,
qpdf_data newpage_qpdf, qpdf_oh newpage,
QPDF_BOOL first);
/* addPageAt() */
QPDF_DLL
QPDF_ERROR_CODE qpdf_add_page_at(
qpdf_data qpdf,
qpdf_data newpage_qpdf, qpdf_oh newpage,
QPDF_BOOL before, qpdf_oh refpage);
/* removePage() */
QPDF_DLL
QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page);
#ifdef __cplusplus
}
#endif

View File

@ -1579,3 +1579,102 @@ char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh)
return qpdf->tmp_string.c_str();
});
}
int qpdf_get_num_pages(qpdf_data qpdf)
{
QTC::TC("qpdf", "qpdf-c called qpdf_num_pages");
int n = -1;
QPDF_ERROR_CODE code = trap_errors(qpdf, [&n](qpdf_data q) {
n = QIntC::to_int(q->qpdf->getAllPages().size());
});
if (code & QPDF_ERRORS)
{
return -1;
}
return n;
}
qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t i)
{
QTC::TC("qpdf", "qpdf-c called qpdf_get_page_n");
qpdf_oh result = 0;
QPDF_ERROR_CODE code = trap_errors(qpdf, [&result, i](qpdf_data q) {
result = new_object(q, q->qpdf->getAllPages().at(i));
});
if ((code & QPDF_ERRORS) || (result == 0))
{
return qpdf_oh_new_uninitialized(qpdf);
}
return result;
}
QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf)
{
QTC::TC("qpdf", "qpdf-c called qpdf_update_all_pages_cache");
return trap_errors(qpdf, [](qpdf_data q) {
q->qpdf->updateAllPagesCache();
});
}
int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation)
{
QTC::TC("qpdf", "qpdf-c called qpdf_find_page_by_id");
int n = -1;
QPDFObjGen og(objid, generation);
QPDF_ERROR_CODE code = trap_errors(qpdf, [&n, &og](qpdf_data q) {
n = QIntC::to_int(q->qpdf->findPage(og));
});
if (code & QPDF_ERRORS)
{
return -1;
}
return n;
}
int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh)
{
QTC::TC("qpdf", "qpdf-c called qpdf_find_page_by_oh");
return do_with_oh<int>(
qpdf, oh, return_T<int>(-1), [qpdf](QPDFObjectHandle& o) {
return qpdf->qpdf->findPage(o);
});
}
QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf)
{
QTC::TC("qpdf", "qpdf-c called qpdf_push_inherited_attributes_to_page");
return trap_errors(qpdf, [](qpdf_data q) {
q->qpdf->pushInheritedAttributesToPage();
});
}
QPDF_ERROR_CODE qpdf_add_page(
qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL first)
{
QTC::TC("qpdf", "qpdf-c called qpdf_add_page");
auto page = qpdf_oh_item_internal(newpage_qpdf, newpage);
return trap_errors(qpdf, [&page, first](qpdf_data q) {
q->qpdf->addPage(page, first);
});
}
QPDF_ERROR_CODE qpdf_add_page_at(
qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage,
QPDF_BOOL before, qpdf_oh refpage)
{
QTC::TC("qpdf", "qpdf-c called qpdf_add_page_at");
auto page = qpdf_oh_item_internal(newpage_qpdf, newpage);
auto ref = qpdf_oh_item_internal(qpdf, refpage);
return trap_errors(qpdf, [&page, before, &ref](qpdf_data q) {
q->qpdf->addPageAt(page, before, ref);
});
}
QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page)
{
QTC::TC("qpdf", "qpdf-c called qpdf_remove_page");
auto p = qpdf_oh_item_internal(qpdf, page);
return trap_errors(qpdf, [&p](qpdf_data q) {
q->qpdf->removePage(p);
});
}

View File

@ -3626,7 +3626,9 @@ For a detailed list of changes, please see the file
more detail what the behavior is. See :ref:`ref.object-accessors` for a more in-depth
discussion.
- Overhaul error handling for the object handle functions in the
- C API Enhancements
- Overhaul error handling for the object handle functions
C API. See comments in the "Object handling" section of
:file:`include/qpdf/qpdf-c.h` for details.
In particular, exceptions thrown by the underlying C++ code
@ -3650,6 +3652,9 @@ For a detailed list of changes, please see the file
and ``qpdf_replace_object``, exposing the corresponding methods
in ``QPDF`` and ``QPDFObjectHandle``.
- Add several functions for working with pages. See ``PAGE
FUNCTIONS`` in ``include/qpdf/qpdf-c.h`` for details.
- Documentation change
- The documentation sources have been switched from docbook to

View File

@ -931,6 +931,138 @@ static void test33(char const* infile,
report_errors();
}
static void test34(char const* infile,
char const* password,
char const* outfile,
char const* xarg)
{
/* This test expects 11-pages.pdf as file1 and minimal.pdf as xarg. */
/* Non-error cases for page API */
qpdf_data qpdf2 = qpdf_init();
assert(qpdf_read(qpdf, infile, password) == 0);
assert(qpdf_read(qpdf2, xarg, "") == 0);
assert(qpdf_get_num_pages(qpdf) == 11);
assert(qpdf_get_num_pages(qpdf2) == 1);
/* At this time, there is no C API for accessing stream data, so
* we hard-code object IDs from a known input file.
*/
assert(qpdf_oh_get_object_id(qpdf, qpdf_get_page_n(qpdf, 0)) == 4);
assert(qpdf_oh_get_object_id(qpdf, qpdf_get_page_n(qpdf, 10)) == 14);
qpdf_oh page3 = qpdf_get_page_n(qpdf, 3);
assert(qpdf_find_page_by_oh(qpdf, page3) == 3);
assert(qpdf_find_page_by_id(
qpdf, qpdf_oh_get_object_id(qpdf, page3), 0) == 3);
/* Add other page to the end */
qpdf_oh opage0 = qpdf_get_page_n(qpdf2, 0);
assert(qpdf_add_page(qpdf, qpdf2, opage0, QPDF_FALSE) == 0);
/* Add other page before page 3 */
assert(qpdf_add_page_at(qpdf, qpdf2, opage0, QPDF_TRUE, page3) == 0);
/* Remove page 3 */
assert(qpdf_remove_page(qpdf, page3) == 0);
/* At page 3 back at the beginning */
assert(qpdf_add_page(qpdf, qpdf, page3, QPDF_TRUE) == 0);
qpdf_init_write(qpdf, outfile);
qpdf_set_static_ID(qpdf, QPDF_TRUE);
qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
qpdf_write(qpdf);
report_errors();
qpdf_cleanup(&qpdf2);
}
static void test35(char const* infile,
char const* password,
char const* outfile,
char const* xarg)
{
/* This test uses 11-pages.pdf */
assert(qpdf_get_num_pages(qpdf) == -1);
assert(qpdf_has_error(qpdf));
qpdf_error e = qpdf_get_error(qpdf);
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
assert(! qpdf_has_error(qpdf));
assert(qpdf_read(qpdf, infile, password) == 0);
qpdf_oh range = qpdf_get_page_n(qpdf, 11);
assert(! qpdf_oh_is_initialized(qpdf, range));
assert(qpdf_has_error(qpdf));
e = qpdf_get_error(qpdf);
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
assert(! qpdf_has_error(qpdf));
assert(qpdf_find_page_by_id(qpdf, 100, 0) == -1);
assert(qpdf_has_error(qpdf));
e = qpdf_get_error(qpdf);
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
assert(! qpdf_has_error(qpdf));
assert(qpdf_find_page_by_oh(qpdf, qpdf_get_root(qpdf)) == -1);
assert(qpdf_more_warnings(qpdf));
e = qpdf_next_warning(qpdf);
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
assert(! qpdf_has_error(qpdf));
assert(qpdf_find_page_by_id(qpdf, 100, 0) == -1);
assert(qpdf_has_error(qpdf));
e = qpdf_get_error(qpdf);
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
assert(! qpdf_has_error(qpdf));
assert(qpdf_add_page(qpdf, qpdf, 1000, QPDF_FALSE) != 0);
report_errors();
}
static void test36(char const* infile,
char const* password,
char const* outfile,
char const* xarg)
{
/* This test uses inherited-rotate.pdf */
assert(qpdf_read(qpdf, infile, password) == 0);
/* Non-trivially push inherited attributes */
qpdf_oh page0 = qpdf_get_object_by_id(qpdf, 3, 0);
assert(qpdf_oh_is_dictionary(qpdf, page0));
qpdf_oh r = qpdf_oh_get_key(qpdf, page0, "/Rotate");
assert(qpdf_oh_get_int_value(qpdf, r) == 90);
qpdf_oh_remove_key(qpdf, page0, "/Rotate");
assert(! qpdf_oh_has_key(qpdf, page0, "/Rotate"));
assert(qpdf_push_inherited_attributes_to_page(qpdf) == 0);
r = qpdf_oh_get_key(qpdf, page0, "/Rotate");
assert(qpdf_oh_get_int_value(qpdf, r) == 270);
assert(qpdf_add_page(qpdf, qpdf, page0, QPDF_TRUE) == 0);
}
static void test37(char const* infile,
char const* password,
char const* outfile,
char const* xarg)
{
/* This test uses 11-pages.pdf */
/* Manually manipulate pages tree */
assert(qpdf_read(qpdf, infile, password) == 0);
assert(qpdf_get_num_pages(qpdf) == 11);
qpdf_oh pages = qpdf_get_object_by_id(qpdf, 3, 0);
qpdf_oh kids = qpdf_oh_get_key(qpdf, pages, "/Kids");
assert(qpdf_oh_get_array_n_items(qpdf, kids) == 11);
qpdf_oh_erase_item(qpdf, kids, 0);
assert(qpdf_get_num_pages(qpdf) == 11);
assert(qpdf_update_all_pages_cache(qpdf) == 0);
assert(qpdf_get_num_pages(qpdf) == 10);
}
int main(int argc, char* argv[])
{
char* p = 0;
@ -1004,6 +1136,10 @@ int main(int argc, char* argv[])
(n == 31) ? test31 :
(n == 32) ? test32 :
(n == 33) ? test33 :
(n == 34) ? test34 :
(n == 35) ? test35 :
(n == 36) ? test36 :
(n == 37) ? test37 :
0);
if (fn == 0)

View File

@ -608,3 +608,12 @@ qpdf-c registered oh error handler 0
qpdf-c cleanup warned about unhandled error 0
qpdf-c called qpdf_get_object_by_id 0
qpdf-c called qpdf_replace_object 0
qpdf-c called qpdf_num_pages 0
qpdf-c called qpdf_get_page_n 0
qpdf-c called qpdf_update_all_pages_cache 0
qpdf-c called qpdf_find_page_by_id 0
qpdf-c called qpdf_find_page_by_oh 0
qpdf-c called qpdf_push_inherited_attributes_to_page 0
qpdf-c called qpdf_add_page 0
qpdf-c called qpdf_add_page_at 0
qpdf-c called qpdf_remove_page 0

View File

@ -4868,6 +4868,36 @@ $td->runtest("C get object by ID",
{$td->STRING => "", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
show_ntests();
# ----------
$td->notify("--- C API Page Functions ---");
$n_tests += 5;
$td->runtest("C page normal",
{$td->COMMAND =>
"qpdf-ctest 34 11-pages.pdf '' a.pdf minimal.pdf"},
{$td->STRING => "", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->runtest("check output",
{$td->FILE => 'a.pdf'},
{$td->FILE => 'c-pages.pdf'});
$td->runtest("C page errors",
{$td->COMMAND =>
"qpdf-ctest 35 11-pages.pdf '' ''"},
{$td->FILE => "c-page-errors.out", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->runtest("C inherited page resources",
{$td->COMMAND =>
"qpdf-ctest 36 inherited-rotate.pdf '' ''"},
{$td->STRING => "", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->runtest("C pages cache",
{$td->COMMAND =>
"qpdf-ctest 37 11-pages.pdf '' ''"},
{$td->STRING => "", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
show_ntests();
# ----------
$td->notify("--- Content Preservation Tests ---");

View File

@ -0,0 +1,8 @@
11-pages.pdf (page object: object 1 0): page object not referenced in /Pages tree
11-pages.pdf (C API object handle 1000): attempted access to unknown object handle
WARNING: object 27 0: operation for dictionary attempted on object of type null: ignoring key replacement request
warning: object 27 0: operation for dictionary attempted on object of type null: ignoring key replacement request
code: 7
file:
pos : 0
text: operation for dictionary attempted on object of type null: ignoring key replacement request

599
qpdf/qtest/qpdf/c-pages.pdf Normal file
View File

@ -0,0 +1,599 @@
%PDF-1.4
%¿÷¢þ
%QDF-1.0
1 0 obj
<<
/Pages 3 0 R
/Type /Catalog
>>
endobj
2 0 obj
<<
/CreationDate (D:20120721200217)
/Producer (Apex PDFWriter)
>>
endobj
3 0 obj
<<
/Count 13
/Kids [
4 0 R
5 0 R
6 0 R
7 0 R
8 0 R
9 0 R
10 0 R
11 0 R
12 0 R
13 0 R
14 0 R
15 0 R
16 0 R
]
/Type /Pages
>>
endobj
%% Page 1
4 0 obj
<<
/Contents 17 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 2
5 0 obj
<<
/Contents 20 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 3
6 0 obj
<<
/Contents 22 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 4
7 0 obj
<<
/Contents 24 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 5
8 0 obj
<<
/Contents 26 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 28 0 R
>>
/ProcSet 29 0 R
>>
/Type /Page
>>
endobj
%% Page 6
9 0 obj
<<
/Contents 30 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 7
10 0 obj
<<
/Contents 32 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 8
11 0 obj
<<
/Contents 34 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 9
12 0 obj
<<
/Contents 36 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 10
13 0 obj
<<
/Contents 38 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 11
14 0 obj
<<
/Contents 40 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 12
15 0 obj
<<
/Contents 42 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 19 0 R
>>
/ProcSet [
/PDF
/Text
]
>>
/Type /Page
>>
endobj
%% Page 13
16 0 obj
<<
/Contents 26 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 28 0 R
>>
/ProcSet 29 0 R
>>
/Type /Page
>>
endobj
%% Contents for page 1
17 0 obj
<<
/Length 18 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 4) Tj ET
endstream
endobj
18 0 obj
47
endobj
19 0 obj
<<
/BaseFont /Times-Roman
/Encoding /WinAnsiEncoding
/Subtype /Type1
/Type /Font
>>
endobj
%% Contents for page 2
20 0 obj
<<
/Length 21 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 1) Tj ET
endstream
endobj
21 0 obj
47
endobj
%% Contents for page 3
22 0 obj
<<
/Length 23 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
endstream
endobj
23 0 obj
47
endobj
%% Contents for page 4
24 0 obj
<<
/Length 25 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET
endstream
endobj
25 0 obj
47
endobj
%% Contents for page 13
26 0 obj
<<
/Length 27 0 R
>>
stream
BT
/F1 24 Tf
72 720 Td
(Potato) Tj
ET
endstream
endobj
27 0 obj
44
endobj
28 0 obj
<<
/BaseFont /Helvetica
/Encoding /WinAnsiEncoding
/Name /F1
/Subtype /Type1
/Type /Font
>>
endobj
29 0 obj
[
/PDF
/Text
]
endobj
%% Contents for page 6
30 0 obj
<<
/Length 31 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 5) Tj ET
endstream
endobj
31 0 obj
47
endobj
%% Contents for page 7
32 0 obj
<<
/Length 33 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 6) Tj ET
endstream
endobj
33 0 obj
47
endobj
%% Contents for page 8
34 0 obj
<<
/Length 35 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 7) Tj ET
endstream
endobj
35 0 obj
47
endobj
%% Contents for page 9
36 0 obj
<<
/Length 37 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 8) Tj ET
endstream
endobj
37 0 obj
47
endobj
%% Contents for page 10
38 0 obj
<<
/Length 39 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 9) Tj ET
endstream
endobj
39 0 obj
47
endobj
%% Contents for page 11
40 0 obj
<<
/Length 41 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 10) Tj ET
endstream
endobj
41 0 obj
48
endobj
%% Contents for page 12
42 0 obj
<<
/Length 43 0 R
>>
stream
BT /F1 15 Tf 72 720 Td (Original page 11) Tj ET
endstream
endobj
43 0 obj
48
endobj
xref
0 44
0000000000 65535 f
0000000025 00000 n
0000000079 00000 n
0000000165 00000 n
0000000375 00000 n
0000000604 00000 n
0000000833 00000 n
0000001062 00000 n
0000001291 00000 n
0000001496 00000 n
0000001725 00000 n
0000001955 00000 n
0000002185 00000 n
0000002416 00000 n
0000002647 00000 n
0000002878 00000 n
0000003109 00000 n
0000003328 00000 n
0000003432 00000 n
0000003452 00000 n
0000003584 00000 n
0000003688 00000 n
0000003731 00000 n
0000003835 00000 n
0000003878 00000 n
0000003982 00000 n
0000004026 00000 n
0000004127 00000 n
0000004147 00000 n
0000004266 00000 n
0000004325 00000 n
0000004429 00000 n
0000004472 00000 n
0000004576 00000 n
0000004619 00000 n
0000004723 00000 n
0000004766 00000 n
0000004870 00000 n
0000004914 00000 n
0000005018 00000 n
0000005062 00000 n
0000005167 00000 n
0000005211 00000 n
0000005316 00000 n
trailer <<
/Info 2 0 R
/Root 1 0 R
/Size 44
/ID [<e032a88c7a987db6ca3abee555506ccc><31415926535897932384626433832795>]
>>
startxref
5336
%%EOF