mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Add JSON v2 support to C API
This commit is contained in:
parent
66f1fd2ad9
commit
f1a2d3160a
@ -1,5 +1,11 @@
|
||||
2022-09-08 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* Added new functions to the C API to support qpdf JSON:
|
||||
qpdf_create_from_json_file, qpdf_create_from_json_data,
|
||||
qpdf_update_from_json_file, qpdf_update_from_json_data, and
|
||||
qpdf_write_json. Examples can be found in qpdf-ctest.c (in the
|
||||
source tree), tests 42 through 47.
|
||||
|
||||
* Add QPDFObjectHandle::isDestroyed() to test whether an indirect
|
||||
object was from a QPDF that has been destroyed.
|
||||
|
||||
|
6
TODO
6
TODO
@ -8,12 +8,6 @@ Always
|
||||
Next
|
||||
====
|
||||
|
||||
Before Release:
|
||||
|
||||
* Support json v2 in the C API. At a minimum, write_json,
|
||||
create_from_json, and update_from_json need to be there and should
|
||||
take the same kinds of functions as the C API for logger.
|
||||
|
||||
Pending changes:
|
||||
|
||||
* Consider also exposing a way to set a new logger and to get the
|
||||
|
@ -257,8 +257,6 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE qpdf_check_pdf(qpdf_data qpdf);
|
||||
|
||||
/* READ FUNCTIONS */
|
||||
|
||||
/* READ PARAMETER FUNCTIONS -- must be called before qpdf_read */
|
||||
|
||||
QPDF_DLL
|
||||
@ -267,6 +265,10 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
void qpdf_set_attempt_recovery(qpdf_data qpdf, QPDF_BOOL value);
|
||||
|
||||
/* PROCESS FUNCTIONS */
|
||||
|
||||
/* This functions process a PDF or JSON input source. */
|
||||
|
||||
/* Calling qpdf_read causes processFile to be called in the C++
|
||||
* API. Basic parsing is performed, but data from the file is
|
||||
* only read as needed. For files without passwords, pass a null
|
||||
@ -297,8 +299,40 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf);
|
||||
|
||||
/* Read functions below must be called after qpdf_read or
|
||||
* qpdf_read_memory. */
|
||||
/* Create a PDF from a JSON file. This calls createFromJSON in the
|
||||
* C++ API.
|
||||
*/
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_create_from_json_file(qpdf_data qpdf, char const* filename);
|
||||
|
||||
/* Create a PDF from JSON data in a null-terminated string. This
|
||||
* calls createFromJSON in the C++ API.
|
||||
*/
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_create_from_json_data(
|
||||
qpdf_data qpdf, char const* buffer, unsigned long long size);
|
||||
|
||||
/* JSON UPDATE FUNCTIONS */
|
||||
|
||||
/* Update a QPDF object from a JSON file or buffer. These
|
||||
* functions call updateFromJSON. One of the other processing
|
||||
* functions has to be called first so that the QPDF object is
|
||||
* initialized with PDF data.
|
||||
*/
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_update_from_json_file(qpdf_data qpdf, char const* filename);
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_update_from_json_data(
|
||||
qpdf_data qpdf, char const* buffer, unsigned long long size);
|
||||
|
||||
/* READ FUNCTIONS */
|
||||
|
||||
/* Read functions below must be called after qpdf_read or any of
|
||||
* the other functions that process a PDF. */
|
||||
|
||||
/*
|
||||
* NOTE: Functions that return char* are returning a pointer to an
|
||||
@ -371,6 +405,39 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
QPDF_BOOL qpdf_allow_modify_all(qpdf_data qpdf);
|
||||
|
||||
/* JSON WRITE FUNCTIONS */
|
||||
|
||||
/* This function serializes the PDF to JSON. This calls writeJSON
|
||||
* from the C++ API.
|
||||
*
|
||||
* - version: the JSON version, currently must be 2
|
||||
* - fn: a function that will be called with blocks of JSON data;
|
||||
* will be called with data, a length, and the value of the
|
||||
* udata parameter to this function
|
||||
* - udata: will be passed as the third argument to fn with each
|
||||
* call; use this for your own tracking or pass a null pointer
|
||||
* if you don't need it
|
||||
* - For decode_level, json_stream_data, file_prefix, and
|
||||
* wanted_objects, see comments in QPDF.hh. For this API,
|
||||
* wanted_objects should be a null-terminated array of
|
||||
* null-terminated strings. Pass a null pointer if you want all
|
||||
* objects.
|
||||
*/
|
||||
|
||||
/* Function should return 0 on success. */
|
||||
typedef int (*qpdf_write_fn_t)(char const* data, size_t len, void* udata);
|
||||
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE qpdf_write_json(
|
||||
qpdf_data qpdf,
|
||||
int version,
|
||||
qpdf_write_fn_t fn,
|
||||
void* udata,
|
||||
enum qpdf_stream_decode_level_e decode_level,
|
||||
enum qpdf_json_stream_data_e json_stream_data,
|
||||
char const* file_prefix,
|
||||
char const* const* wanted_objects);
|
||||
|
||||
/* WRITE FUNCTIONS */
|
||||
|
||||
/* Set up for writing. No writing is actually performed until the
|
||||
|
@ -2,8 +2,10 @@
|
||||
|
||||
#include <qpdf/QPDF.hh>
|
||||
|
||||
#include <qpdf/BufferInputSource.hh>
|
||||
#include <qpdf/Pl_Buffer.hh>
|
||||
#include <qpdf/Pl_Discard.hh>
|
||||
#include <qpdf/Pl_Function.hh>
|
||||
#include <qpdf/QIntC.hh>
|
||||
#include <qpdf/QPDFExc.hh>
|
||||
#include <qpdf/QPDFLogger.hh>
|
||||
@ -2029,3 +2031,89 @@ qpdf_remove_page(qpdf_data qpdf, qpdf_oh page)
|
||||
auto p = qpdf_oh_item_internal(qpdf, page);
|
||||
return trap_errors(qpdf, [&p](qpdf_data q) { q->qpdf->removePage(p); });
|
||||
}
|
||||
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_create_from_json_file(qpdf_data qpdf, char const* filename)
|
||||
{
|
||||
QPDF_ERROR_CODE status = QPDF_SUCCESS;
|
||||
qpdf->filename = filename;
|
||||
status = trap_errors(
|
||||
qpdf, [](qpdf_data q) { q->qpdf->createFromJSON(q->filename); });
|
||||
return status;
|
||||
}
|
||||
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_create_from_json_data(
|
||||
qpdf_data qpdf, char const* buffer, unsigned long long size)
|
||||
{
|
||||
QPDF_ERROR_CODE status = QPDF_SUCCESS;
|
||||
qpdf->filename = "json buffer";
|
||||
qpdf->buffer = buffer;
|
||||
qpdf->size = size;
|
||||
auto b =
|
||||
new Buffer(QUtil::unsigned_char_pointer(buffer), QIntC::to_size(size));
|
||||
auto is = std::make_shared<BufferInputSource>(qpdf->filename, b, true);
|
||||
status =
|
||||
trap_errors(qpdf, [&is](qpdf_data q) { q->qpdf->createFromJSON(is); });
|
||||
return status;
|
||||
}
|
||||
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_update_from_json_file(qpdf_data qpdf, char const* filename)
|
||||
{
|
||||
QPDF_ERROR_CODE status = QPDF_SUCCESS;
|
||||
status = trap_errors(
|
||||
qpdf, [filename](qpdf_data q) { q->qpdf->updateFromJSON(filename); });
|
||||
return status;
|
||||
}
|
||||
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_update_from_json_data(
|
||||
qpdf_data qpdf, char const* buffer, unsigned long long size)
|
||||
{
|
||||
QPDF_ERROR_CODE status = QPDF_SUCCESS;
|
||||
auto b =
|
||||
new Buffer(QUtil::unsigned_char_pointer(buffer), QIntC::to_size(size));
|
||||
auto is = std::make_shared<BufferInputSource>(qpdf->filename, b, true);
|
||||
status =
|
||||
trap_errors(qpdf, [&is](qpdf_data q) { q->qpdf->updateFromJSON(is); });
|
||||
return status;
|
||||
}
|
||||
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_write_json(
|
||||
qpdf_data qpdf,
|
||||
int version,
|
||||
qpdf_write_fn_t fn,
|
||||
void* udata,
|
||||
enum qpdf_stream_decode_level_e decode_level,
|
||||
enum qpdf_json_stream_data_e json_stream_data,
|
||||
char const* file_prefix,
|
||||
char const* const* wanted_objects)
|
||||
{
|
||||
QPDF_ERROR_CODE status = QPDF_SUCCESS;
|
||||
auto p = std::make_shared<Pl_Function>("write_json", nullptr, fn, udata);
|
||||
std::set<std::string> wanted_objects_set;
|
||||
if (wanted_objects) {
|
||||
for (auto i = wanted_objects; *i; ++i) {
|
||||
wanted_objects_set.insert(*i);
|
||||
}
|
||||
}
|
||||
status = trap_errors(
|
||||
qpdf,
|
||||
[version,
|
||||
p,
|
||||
decode_level,
|
||||
json_stream_data,
|
||||
file_prefix,
|
||||
&wanted_objects_set](qpdf_data q) {
|
||||
q->qpdf->writeJSON(
|
||||
version,
|
||||
p.get(),
|
||||
decode_level,
|
||||
json_stream_data,
|
||||
file_prefix,
|
||||
wanted_objects_set);
|
||||
});
|
||||
return status;
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ For a detailed list of changes, please see the file
|
||||
- New C++ API calls: ``QPDF::writeJSON``,
|
||||
``QPDF::createFromJSON``, ``QPDF::updateFromJSON``
|
||||
|
||||
- New C API calls: ``qpdf_create_from_json_file``,
|
||||
``qpdf_create_from_json_data``, ``qpdf_update_from_json_file``,
|
||||
``qpdf_update_from_json_data``, and ``qpdf_write_json``.
|
||||
|
||||
- Complete documentation can be found at :ref:`json`. A
|
||||
comprehensive list of changes from version 1 to version 2 can be
|
||||
found at :ref:`json-v2-changes`.
|
||||
|
@ -133,6 +133,13 @@ count_progress(int percent, void* data)
|
||||
++(*(int*)data);
|
||||
}
|
||||
|
||||
static int
|
||||
write_to_file(char const* data, size_t size, void* udata)
|
||||
{
|
||||
FILE* f = (FILE*)udata;
|
||||
return fwrite(data, 1, size, f) != size;
|
||||
}
|
||||
|
||||
static void
|
||||
test01(
|
||||
char const* infile,
|
||||
@ -1458,7 +1465,7 @@ test41(
|
||||
char const* outfile,
|
||||
char const* xarg)
|
||||
{
|
||||
/* Empty PDF -- infile is ignored*/
|
||||
/* Empty PDF -- infile is ignored */
|
||||
assert(qpdf_empty_pdf(qpdf) == 0);
|
||||
qpdf_init_write(qpdf, outfile);
|
||||
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
||||
@ -1466,6 +1473,110 @@ test41(
|
||||
report_errors();
|
||||
}
|
||||
|
||||
static void
|
||||
test42(
|
||||
char const* infile,
|
||||
char const* password,
|
||||
char const* outfile,
|
||||
char const* xarg)
|
||||
{
|
||||
assert(qpdf_create_from_json_file(qpdf, infile) == QPDF_SUCCESS);
|
||||
qpdf_init_write(qpdf, outfile);
|
||||
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
||||
qpdf_write(qpdf);
|
||||
report_errors();
|
||||
}
|
||||
|
||||
static void
|
||||
test43(
|
||||
char const* infile,
|
||||
char const* password,
|
||||
char const* outfile,
|
||||
char const* xarg)
|
||||
{
|
||||
char* buf = NULL;
|
||||
unsigned long size = 0;
|
||||
read_file_into_memory(infile, &buf, &size);
|
||||
assert(qpdf_create_from_json_data(qpdf, buf, size) == QPDF_SUCCESS);
|
||||
qpdf_init_write(qpdf, outfile);
|
||||
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
||||
qpdf_write(qpdf);
|
||||
report_errors();
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
test44(
|
||||
char const* infile,
|
||||
char const* password,
|
||||
char const* outfile,
|
||||
char const* xarg)
|
||||
{
|
||||
assert(qpdf_read(qpdf, infile, password) == 0);
|
||||
assert(qpdf_update_from_json_file(qpdf, xarg) == QPDF_SUCCESS);
|
||||
qpdf_init_write(qpdf, outfile);
|
||||
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
||||
qpdf_write(qpdf);
|
||||
report_errors();
|
||||
}
|
||||
|
||||
static void
|
||||
test45(
|
||||
char const* infile,
|
||||
char const* password,
|
||||
char const* outfile,
|
||||
char const* xarg)
|
||||
{
|
||||
char* buf = NULL;
|
||||
unsigned long size = 0;
|
||||
read_file_into_memory(xarg, &buf, &size);
|
||||
assert(qpdf_read(qpdf, infile, password) == 0);
|
||||
assert(qpdf_update_from_json_data(qpdf, buf, size) == QPDF_SUCCESS);
|
||||
qpdf_init_write(qpdf, outfile);
|
||||
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
||||
qpdf_write(qpdf);
|
||||
report_errors();
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
test46(
|
||||
char const* infile,
|
||||
char const* password,
|
||||
char const* outfile,
|
||||
char const* xarg)
|
||||
{
|
||||
FILE* f = safe_fopen(outfile, "wb");
|
||||
assert(qpdf_read(qpdf, infile, password) == 0);
|
||||
qpdf_write_json(
|
||||
qpdf, 2, write_to_file, f, qpdf_dl_none, qpdf_sj_inline, "", NULL);
|
||||
fclose(f);
|
||||
report_errors();
|
||||
}
|
||||
|
||||
static void
|
||||
test47(
|
||||
char const* infile,
|
||||
char const* password,
|
||||
char const* outfile,
|
||||
char const* xarg)
|
||||
{
|
||||
FILE* f = safe_fopen(outfile, "wb");
|
||||
assert(qpdf_read(qpdf, infile, password) == 0);
|
||||
char const* wanted_objects[] = {"obj:4 0 R", "trailer", NULL};
|
||||
qpdf_write_json(
|
||||
qpdf,
|
||||
2,
|
||||
write_to_file,
|
||||
f,
|
||||
qpdf_dl_specialized,
|
||||
qpdf_sj_file,
|
||||
xarg,
|
||||
wanted_objects);
|
||||
fclose(f);
|
||||
report_errors();
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
@ -1542,6 +1653,12 @@ main(int argc, char* argv[])
|
||||
: (n == 39) ? test39
|
||||
: (n == 40) ? test40
|
||||
: (n == 41) ? test41
|
||||
: (n == 42) ? test42
|
||||
: (n == 43) ? test43
|
||||
: (n == 44) ? test44
|
||||
: (n == 45) ? test45
|
||||
: (n == 46) ? test46
|
||||
: (n == 47) ? test47
|
||||
: 0);
|
||||
|
||||
if (fn == 0) {
|
||||
|
@ -288,5 +288,58 @@ $td->runtest("simple version of writeJSON",
|
||||
{$td->FILE => "minimal-write-json.json", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$n_tests += 13;
|
||||
$td->runtest("C API create from json file",
|
||||
{$td->COMMAND => "qpdf-ctest 42 minimal.json '' a.pdf"},
|
||||
{$td->STRING => "C test 42 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check C API create from file",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "qpdf-ctest-42-43.pdf"});
|
||||
$td->runtest("C API create from json buffer",
|
||||
{$td->COMMAND => "qpdf-ctest 43 minimal.json '' a.pdf"},
|
||||
{$td->STRING => "C test 43 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check C API create from buffer",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "qpdf-ctest-42-43.pdf"});
|
||||
$td->runtest("C API update from json file",
|
||||
{$td->COMMAND =>
|
||||
"qpdf-ctest 44 minimal.pdf '' a.pdf minimal-update.json"},
|
||||
{$td->STRING => "C test 44 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check C API update from file",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "qpdf-ctest-44-45.pdf"});
|
||||
$td->runtest("C API update from json buffer",
|
||||
{$td->COMMAND =>
|
||||
"qpdf-ctest 45 minimal.pdf '' a.pdf minimal-update.json"},
|
||||
{$td->STRING => "C test 45 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check C API update from buffer",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "qpdf-ctest-44-45.pdf"});
|
||||
$td->runtest("C API write to JSON 1",
|
||||
{$td->COMMAND =>
|
||||
"qpdf-ctest 46 minimal.pdf '' a.json"},
|
||||
{$td->STRING => "C test 46 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check C API write to JSON 1",
|
||||
{$td->FILE => "a.json"},
|
||||
{$td->FILE => "qpdf-ctest-46.json"},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("C API write to JSON 2",
|
||||
{$td->COMMAND =>
|
||||
"qpdf-ctest 47 minimal.pdf '' a.json auto"},
|
||||
{$td->STRING => "C test 47 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check C API write to JSON 2",
|
||||
{$td->FILE => "a.json"},
|
||||
{$td->FILE => "qpdf-ctest-47.json"},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check C API write to JSON stream",
|
||||
{$td->FILE => "auto-4"},
|
||||
{$td->FILE => "qpdf-ctest-47-4"});
|
||||
|
||||
cleanup();
|
||||
$td->report($n_tests);
|
||||
|
17
qpdf/qtest/qpdf/minimal-update.json
Normal file
17
qpdf/qtest/qpdf/minimal-update.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"qpdf": [
|
||||
{
|
||||
"jsonversion": 2,
|
||||
"pushedinheritedpageresources": false,
|
||||
"calledgetallpages": false
|
||||
},
|
||||
{
|
||||
"obj:4 0 R": {
|
||||
"stream": {
|
||||
"data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoU2FsYWQpIFRqCkVUCg==",
|
||||
"dict": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
74
qpdf/qtest/qpdf/minimal.json
Normal file
74
qpdf/qtest/qpdf/minimal.json
Normal file
@ -0,0 +1,74 @@
|
||||
{
|
||||
"qpdf": [
|
||||
{
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "1.3",
|
||||
"pushedinheritedpageresources": false,
|
||||
"calledgetallpages": false,
|
||||
"maxobjectid": 6
|
||||
},
|
||||
{
|
||||
"obj:1 0 R": {
|
||||
"value": {
|
||||
"/Pages": "2 0 R",
|
||||
"/Type": "/Catalog"
|
||||
}
|
||||
},
|
||||
"obj:2 0 R": {
|
||||
"value": {
|
||||
"/Count": 1,
|
||||
"/Kids": [
|
||||
"3 0 R"
|
||||
],
|
||||
"/Type": "/Pages"
|
||||
}
|
||||
},
|
||||
"obj:3 0 R": {
|
||||
"value": {
|
||||
"/Contents": "4 0 R",
|
||||
"/MediaBox": [
|
||||
0,
|
||||
0,
|
||||
612,
|
||||
792
|
||||
],
|
||||
"/Parent": "2 0 R",
|
||||
"/Resources": {
|
||||
"/Font": {
|
||||
"/F1": "6 0 R"
|
||||
},
|
||||
"/ProcSet": "5 0 R"
|
||||
},
|
||||
"/Type": "/Page"
|
||||
}
|
||||
},
|
||||
"obj:4 0 R": {
|
||||
"stream": {
|
||||
"data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=",
|
||||
"dict": {}
|
||||
}
|
||||
},
|
||||
"obj:5 0 R": {
|
||||
"value": [
|
||||
"/PDF",
|
||||
"/Text"
|
||||
]
|
||||
},
|
||||
"obj:6 0 R": {
|
||||
"value": {
|
||||
"/BaseFont": "/Helvetica",
|
||||
"/Encoding": "/WinAnsiEncoding",
|
||||
"/Name": "/F1",
|
||||
"/Subtype": "/Type1",
|
||||
"/Type": "/Font"
|
||||
}
|
||||
},
|
||||
"trailer": {
|
||||
"value": {
|
||||
"/Root": "1 0 R",
|
||||
"/Size": 7
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
BIN
qpdf/qtest/qpdf/qpdf-ctest-42-43.pdf
Normal file
BIN
qpdf/qtest/qpdf/qpdf-ctest-42-43.pdf
Normal file
Binary file not shown.
BIN
qpdf/qtest/qpdf/qpdf-ctest-44-45.pdf
Normal file
BIN
qpdf/qtest/qpdf/qpdf-ctest-44-45.pdf
Normal file
Binary file not shown.
74
qpdf/qtest/qpdf/qpdf-ctest-46.json
Normal file
74
qpdf/qtest/qpdf/qpdf-ctest-46.json
Normal file
@ -0,0 +1,74 @@
|
||||
{
|
||||
"qpdf": [
|
||||
{
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "1.3",
|
||||
"pushedinheritedpageresources": false,
|
||||
"calledgetallpages": false,
|
||||
"maxobjectid": 6
|
||||
},
|
||||
{
|
||||
"obj:1 0 R": {
|
||||
"value": {
|
||||
"/Pages": "2 0 R",
|
||||
"/Type": "/Catalog"
|
||||
}
|
||||
},
|
||||
"obj:2 0 R": {
|
||||
"value": {
|
||||
"/Count": 1,
|
||||
"/Kids": [
|
||||
"3 0 R"
|
||||
],
|
||||
"/Type": "/Pages"
|
||||
}
|
||||
},
|
||||
"obj:3 0 R": {
|
||||
"value": {
|
||||
"/Contents": "4 0 R",
|
||||
"/MediaBox": [
|
||||
0,
|
||||
0,
|
||||
612,
|
||||
792
|
||||
],
|
||||
"/Parent": "2 0 R",
|
||||
"/Resources": {
|
||||
"/Font": {
|
||||
"/F1": "6 0 R"
|
||||
},
|
||||
"/ProcSet": "5 0 R"
|
||||
},
|
||||
"/Type": "/Page"
|
||||
}
|
||||
},
|
||||
"obj:4 0 R": {
|
||||
"stream": {
|
||||
"data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=",
|
||||
"dict": {}
|
||||
}
|
||||
},
|
||||
"obj:5 0 R": {
|
||||
"value": [
|
||||
"/PDF",
|
||||
"/Text"
|
||||
]
|
||||
},
|
||||
"obj:6 0 R": {
|
||||
"value": {
|
||||
"/BaseFont": "/Helvetica",
|
||||
"/Encoding": "/WinAnsiEncoding",
|
||||
"/Name": "/F1",
|
||||
"/Subtype": "/Type1",
|
||||
"/Type": "/Font"
|
||||
}
|
||||
},
|
||||
"trailer": {
|
||||
"value": {
|
||||
"/Root": "1 0 R",
|
||||
"/Size": 7
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
5
qpdf/qtest/qpdf/qpdf-ctest-47-4
Normal file
5
qpdf/qtest/qpdf/qpdf-ctest-47-4
Normal file
@ -0,0 +1,5 @@
|
||||
BT
|
||||
/F1 24 Tf
|
||||
72 720 Td
|
||||
(Potato) Tj
|
||||
ET
|
25
qpdf/qtest/qpdf/qpdf-ctest-47.json
Normal file
25
qpdf/qtest/qpdf/qpdf-ctest-47.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"qpdf": [
|
||||
{
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "1.3",
|
||||
"pushedinheritedpageresources": false,
|
||||
"calledgetallpages": false,
|
||||
"maxobjectid": 6
|
||||
},
|
||||
{
|
||||
"obj:4 0 R": {
|
||||
"stream": {
|
||||
"datafile": "auto-4",
|
||||
"dict": {}
|
||||
}
|
||||
},
|
||||
"trailer": {
|
||||
"value": {
|
||||
"/Root": "1 0 R",
|
||||
"/Size": 7
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user