mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Make more QPDFPageObjectHelper methods work with form XObject
This commit is contained in:
parent
98da4fd835
commit
3be58f49e5
12
ChangeLog
12
ChangeLog
@ -1,5 +1,17 @@
|
||||
2021-01-02 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* Make QPDFPageObjectHelper methods pipeContents, parseContents,
|
||||
and addContentTokenFilter work with form XObjects.
|
||||
|
||||
* Rename some QPDFPageObjectHelper methods and make them support
|
||||
form XObjects as well as pages. The old names will be preserved
|
||||
from compatibility.
|
||||
- pipePageContents -> pipeContents
|
||||
- parsePageContents -> parseContents
|
||||
|
||||
* Add QPDFObjectHandle::parseAsContents to apply ParserCallbacks
|
||||
to a form XObject.
|
||||
|
||||
* QPDFPageObjectHelper::externalizeInlineImages can be called with
|
||||
form XObjects as well as pages.
|
||||
|
||||
|
@ -89,7 +89,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
QPDFPageObjectHelper& page = pages.at(QIntC::to_size(pageno-1));
|
||||
ParserCallbacks cb;
|
||||
page.parsePageContents(&cb);
|
||||
page.parseContents(&cb);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
@ -142,7 +142,7 @@ FuzzHelper::testPages()
|
||||
try
|
||||
{
|
||||
page.coalesceContentStreams();
|
||||
page.parsePageContents(&discard_contents);
|
||||
page.parseContents(&discard_contents);
|
||||
page.getImages();
|
||||
pldh.getLabelForPage(pageno);
|
||||
QPDFObjectHandle page_obj(page.getObjectHandle());
|
||||
|
@ -448,7 +448,7 @@ class QPDFObjectHandle
|
||||
void parsePageContents(ParserCallbacks* callbacks);
|
||||
QPDF_DLL
|
||||
void filterPageContents(TokenFilter* filter, Pipeline* next = 0);
|
||||
// See comments for QPDFPageObjectHelper::pipePageContents.
|
||||
// See comments for QPDFPageObjectHelper::pipeContents.
|
||||
QPDF_DLL
|
||||
void pipePageContents(Pipeline* p);
|
||||
QPDF_DLL
|
||||
@ -460,6 +460,10 @@ class QPDFObjectHandle
|
||||
// XObject, whose data is in the same format as a content stream.
|
||||
QPDF_DLL
|
||||
void filterAsContents(TokenFilter* filter, Pipeline* next = 0);
|
||||
// Called on a stream to parse the stream as page contents. This
|
||||
// can be used to parse a form XObject.
|
||||
QPDF_DLL
|
||||
void parseAsContents(ParserCallbacks* callbacks);
|
||||
|
||||
// Type-specific factories
|
||||
QPDF_DLL
|
||||
|
@ -182,7 +182,11 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
|
||||
// Parse a page's contents through ParserCallbacks, described
|
||||
// above. This method works whether the contents are a single
|
||||
// stream or an array of streams. Call on a page object.
|
||||
// stream or an array of streams. Call on a page object. Also
|
||||
// works for form XObjects.
|
||||
QPDF_DLL
|
||||
void parseContents(QPDFObjectHandle::ParserCallbacks* callbacks);
|
||||
// Old name
|
||||
QPDF_DLL
|
||||
void parsePageContents(QPDFObjectHandle::ParserCallbacks* callbacks);
|
||||
|
||||
@ -206,14 +210,17 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
|
||||
// Pipe a page's contents through the given pipeline. This method
|
||||
// works whether the contents are a single stream or an array of
|
||||
// streams.
|
||||
// streams. Also works on form XObjects.
|
||||
QPDF_DLL
|
||||
void pipeContents(Pipeline* p);
|
||||
// Old name
|
||||
QPDF_DLL
|
||||
void pipePageContents(Pipeline* p);
|
||||
|
||||
// Attach a token filter to a page's contents. If the page's
|
||||
// contents is an array of streams, it is automatically coalesced.
|
||||
// The token filter is applied to the page's contents as a single
|
||||
// stream.
|
||||
// stream. Also works on form XObjects.
|
||||
QPDF_DLL
|
||||
void addContentTokenFilter(
|
||||
PointerHolder<QPDFObjectHandle::TokenFilter> token_filter);
|
||||
|
@ -1668,6 +1668,15 @@ QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks)
|
||||
description, callbacks);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFObjectHandle::parseAsContents(ParserCallbacks* callbacks)
|
||||
{
|
||||
std::string description = "object " +
|
||||
QUtil::int_to_string(this->objid) + " " +
|
||||
QUtil::int_to_string(this->generation);
|
||||
this->parseContentStream_internal(description, callbacks);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next)
|
||||
{
|
||||
|
@ -583,9 +583,23 @@ QPDFPageObjectHelper::coalesceContentStreams()
|
||||
void
|
||||
QPDFPageObjectHelper::parsePageContents(
|
||||
QPDFObjectHandle::ParserCallbacks* callbacks)
|
||||
{
|
||||
parseContents(callbacks);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFPageObjectHelper::parseContents(
|
||||
QPDFObjectHandle::ParserCallbacks* callbacks)
|
||||
{
|
||||
if (this->oh.isFormXObject())
|
||||
{
|
||||
this->oh.parseAsContents(callbacks);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->oh.parsePageContents(callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDFPageObjectHelper::filterPageContents(
|
||||
@ -612,16 +626,36 @@ QPDFPageObjectHelper::filterContents(
|
||||
|
||||
void
|
||||
QPDFPageObjectHelper::pipePageContents(Pipeline* p)
|
||||
{
|
||||
pipeContents(p);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFPageObjectHelper::pipeContents(Pipeline* p)
|
||||
{
|
||||
if (this->oh.isFormXObject())
|
||||
{
|
||||
this->oh.pipeStreamData(p, 0, qpdf_dl_specialized);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->oh.pipePageContents(p);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDFPageObjectHelper::addContentTokenFilter(
|
||||
PointerHolder<QPDFObjectHandle::TokenFilter> token_filter)
|
||||
{
|
||||
if (this->oh.isFormXObject())
|
||||
{
|
||||
this->oh.addTokenFilter(token_filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->oh.addContentTokenFilter(token_filter);
|
||||
}
|
||||
}
|
||||
|
||||
class NameWatcher: public QPDFObjectHandle::TokenFilter
|
||||
{
|
||||
|
@ -4893,6 +4893,18 @@ print "\n";
|
||||
<function>filterContents</function>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>pipePageContents</function> to
|
||||
<function>pipeContents</function>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>parsePageContents</function> to
|
||||
<function>parseContents</function>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
@ -3539,7 +3539,7 @@ static void do_check(QPDF& pdf, Options& o, int& exit_code)
|
||||
++pageno;
|
||||
try
|
||||
{
|
||||
page.parsePageContents(&discard_contents);
|
||||
page.parseContents(&discard_contents);
|
||||
}
|
||||
catch (QPDFExc& e)
|
||||
{
|
||||
|
@ -423,7 +423,7 @@ foreach my $i (@choice_values)
|
||||
show_ntests();
|
||||
# ----------
|
||||
$td->notify("--- Form XObject, underlay, overlay ---");
|
||||
$n_tests += 19;
|
||||
$n_tests += 20;
|
||||
|
||||
$td->runtest("form xobject creation",
|
||||
{$td->COMMAND => "test_driver 55 fxo-red.pdf"},
|
||||
@ -491,6 +491,11 @@ $td->runtest("foreach",
|
||||
{$td->FILE => "nested-form-xobjects.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("page operations on form xobject",
|
||||
{$td->COMMAND => "test_driver 72 nested-form-xobjects.pdf"},
|
||||
{$td->FILE => "page-ops-on-form-xobject.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
|
47
qpdf/qtest/qpdf/page-ops-on-form-xobject.out
Normal file
47
qpdf/qtest/qpdf/page-ops-on-form-xobject.out
Normal file
@ -0,0 +1,47 @@
|
||||
--- parseContents ---
|
||||
content size: 173
|
||||
operator, offset=0, length=2: BT
|
||||
name, offset=5, length=3: /F1
|
||||
integer, offset=9, length=2: 24
|
||||
operator, offset=12, length=2: Tf
|
||||
integer, offset=17, length=1: 0
|
||||
integer, offset=19, length=3: 320
|
||||
operator, offset=23, length=2: Td
|
||||
string, offset=28, length=5: (FX1)
|
||||
operator, offset=34, length=2: Tj
|
||||
operator, offset=37, length=2: ET
|
||||
operator, offset=40, length=1: q
|
||||
integer, offset=42, length=3: 100
|
||||
integer, offset=46, length=1: 0
|
||||
integer, offset=48, length=1: 0
|
||||
integer, offset=50, length=3: 100
|
||||
integer, offset=54, length=3: 0
|
||||
integer, offset=58, length=3: 200
|
||||
operator, offset=62, length=2: cm
|
||||
name, offset=65, length=4: /Im1
|
||||
operator, offset=70, length=2: Do
|
||||
operator, offset=73, length=1: Q
|
||||
operator, offset=75, length=1: q
|
||||
integer, offset=77, length=3: 100
|
||||
integer, offset=81, length=1: 0
|
||||
integer, offset=83, length=1: 0
|
||||
integer, offset=85, length=3: 100
|
||||
integer, offset=89, length=3: 120
|
||||
integer, offset=93, length=3: 200
|
||||
operator, offset=97, length=2: cm
|
||||
name, offset=100, length=4: /Im2
|
||||
operator, offset=105, length=2: Do
|
||||
operator, offset=108, length=1: Q
|
||||
operator, offset=110, length=1: q
|
||||
real, offset=112, length=7: 1.00000
|
||||
real, offset=120, length=7: 0.00000
|
||||
real, offset=128, length=7: 0.00000
|
||||
real, offset=136, length=7: 1.00000
|
||||
real, offset=144, length=7: 0.00000
|
||||
real, offset=152, length=7: 0.00000
|
||||
operator, offset=160, length=2: cm
|
||||
name, offset=163, length=4: /Fx1
|
||||
operator, offset=168, length=2: Do
|
||||
operator, offset=171, length=1: Q
|
||||
-EOF-
|
||||
test 72 done
|
@ -1463,7 +1463,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
{
|
||||
QPDFPageObjectHelper& page(*iter);
|
||||
ParserCallbacks cb;
|
||||
page.parsePageContents(&cb);
|
||||
page.parseContents(&cb);
|
||||
}
|
||||
}
|
||||
else if (n == 38)
|
||||
@ -2279,6 +2279,27 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
std::cout << i.first << " -> " << i.second.unparse() << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 72)
|
||||
{
|
||||
// Call some QPDFPageObjectHelper methods on form XObjects.
|
||||
auto page = QPDFPageDocumentHelper(pdf).getAllPages().at(0);
|
||||
auto fx1 = QPDFPageObjectHelper(
|
||||
page.getObjectHandle()
|
||||
.getKey("/Resources")
|
||||
.getKey("/XObject")
|
||||
.getKey("/Fx1"));
|
||||
std::cout << "--- parseContents ---" << std::endl;
|
||||
ParserCallbacks cb;
|
||||
fx1.parseContents(&cb);
|
||||
Pl_Buffer b("buffer");
|
||||
fx1.addContentTokenFilter(new TokenFilter);
|
||||
fx1.pipeContents(&b);
|
||||
std::unique_ptr<Buffer> buf(b.getBuffer());
|
||||
std::string s(
|
||||
reinterpret_cast<char const*>(buf->getBuffer()),
|
||||
buf->getSize());
|
||||
assert(s.find("/bye") != std::string::npos);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(std::string("invalid test ") +
|
||||
|
@ -219,7 +219,7 @@ static void process(char const* filename, bool include_ignorable,
|
||||
{
|
||||
++pageno;
|
||||
Pl_Buffer plb("buffer");
|
||||
(*iter).pipePageContents(&plb);
|
||||
(*iter).pipeContents(&plb);
|
||||
PointerHolder<Buffer> content_data = plb.getBuffer();
|
||||
BufferInputSource* bis = new BufferInputSource(
|
||||
"content data", content_data.getPointer());
|
||||
|
Loading…
Reference in New Issue
Block a user