Importing Existing PDFs

5 views
Skip to first unread message

James Healy

unread,
Nov 5, 2009, 8:31:26 PM11/5/09
to prawn...@googlegroups.com
Hi Folks,

I had some late night inspiration yesterday and hacked out basic support
for importing existing PDFs into prawn. This essentially allows you to
have a template PDF that you can add content to.

At this stage it's rough, but in simple cases as least it seems to work
quite well.

The code is in the templates branch of my fork
(http://github.com/yob/prawn/tree/templates) and it depends on a
PDF::Reader gem from the pdf-reader/hash branch being installed.

The initial API is visible in the example file:
http://github.com/yob/prawn/blob/templates/examples/general/templates.rb

It works by passing the template file path into the ObjectStore
constructor. The ObjectStore then just imports all the objects from the
source file and then uses the existing info and root dictionaries for
the current document.

Theres a sample document at http://gir.deefa.com/template.pdf that has
the fancy_tables.pdf reference file with some added content.

It's far from being ready to merge, but it proves that we should be
able to get something working.

-- James Healy <ji...@deefa.com> Fri, 06 Nov 2009 12:24:14 +1100

Brad Ediger

unread,
Nov 5, 2009, 8:56:20 PM11/5/09
to prawn...@googlegroups.com
On Thu, Nov 5, 2009 at 7:31 PM, James Healy <ji...@deefa.com> wrote:
>
> Hi Folks,
>
> I had some late night inspiration yesterday and hacked out basic support
> for importing existing PDFs into prawn. This essentially allows you to
> have a template PDF that you can add content to.
>
> At this stage it's rough, but in simple cases as least it seems to work
> quite well.
>
> The code is in the templates branch of my fork
> (http://github.com/yob/prawn/tree/templates) and it depends on a
> PDF::Reader gem from the pdf-reader/hash branch being installed.
>
> The initial API is visible in the example file:
> http://github.com/yob/prawn/blob/templates/examples/general/templates.rb
>
> It works by passing the template file path into the ObjectStore
> constructor. The ObjectStore then just imports all the objects from the
> source file and then uses the existing info and root dictionaries for
> the current document.

Nice work! That's a great idea, just importing the old objects. With
some of the work Greg and I did with reopening old pages, and Daniel
Nelson's work on stamps, we're heading toward a few very flexible ways
to reuse content.

I fixed some spec failures and minor typos here:

http://github.com/bradediger/prawn/tree/templates

Cheers!
Brad

James Healy

unread,
Nov 5, 2009, 10:28:00 PM11/5/09
to prawn...@googlegroups.com
Brad Ediger wrote:
> Nice work! That's a great idea, just importing the old objects. With
> some of the work Greg and I did with reopening old pages, and Daniel
> Nelson's work on stamps, we're heading toward a few very flexible ways
> to reuse content.
>
> I fixed some spec failures and minor typos here:

Thanks for the patch, clearly I was tired and had just been hacking at
ObjectStore to get something working. I've merged the patch and added a
few extra ObjectStore specs.

Being able to re-open old pages will be the killer feature here. Without
that, I'd have to change this importing API to let users import the file
1 page at a time after each start_new_page().

-- James Healy <ji...@deefa.com> Fri, 06 Nov 2009 14:27:30 +1100

Brad Ediger

unread,
Nov 5, 2009, 10:48:27 PM11/5/09
to prawn...@googlegroups.com
On Thu, Nov 5, 2009 at 9:28 PM, James Healy <ji...@deefa.com> wrote:
>
> Being able to re-open old pages will be the killer feature here. Without
> that, I'd have to change this importing API to let users import the file
> 1 page at a time after each start_new_page().

As usual, less magic in Prawn. Here's Greg's quick proof-of-concept
code from back when we were hacking at LoneStar RubyConf:

http://gist.github.com/178065

That go_to_page() is golden. We should probably merge that, or
something like it, in 0.7.

Brad

Brad Ediger

unread,
Nov 5, 2009, 10:50:44 PM11/5/09
to prawn...@googlegroups.com
On Thu, Nov 5, 2009 at 9:48 PM, Brad Ediger <br...@bradediger.com> wrote:
> On Thu, Nov 5, 2009 at 9:28 PM, James Healy <ji...@deefa.com> wrote:
>>
>> Being able to re-open old pages will be the killer feature here. Without
>> that, I'd have to change this importing API to let users import the file
>> 1 page at a time after each start_new_page().
>
> As usual, less magic in Prawn. Here's Greg's quick proof-of-concept
> code from back when we were hacking at LoneStar RubyConf:

Oops, better link:

http://gist.github.com/178054

James Healy

unread,
Nov 5, 2009, 11:15:17 PM11/5/09
to prawn...@googlegroups.com
Brad Ediger wrote:
> > As usual, less magic in Prawn. Here's Greg's quick proof-of-concept
> > code from back when we were hacking at LoneStar RubyConf:
>
> Oops, better link:
>
> http://gist.github.com/178054

Wow, nice.

One thing we need to be careful of is the page state. Things like the y
cursor and margins that are currently setup in start_new_page may need
to reinitialized when we move to an existing page.

-- James Healy <ji...@deefa.com> Fri, 06 Nov 2009 15:13:46 +1100

Brad Ediger

unread,
Nov 5, 2009, 11:19:54 PM11/5/09
to prawn...@googlegroups.com
On Thu, Nov 5, 2009 at 10:15 PM, James Healy <ji...@deefa.com> wrote:
>
> One thing we need to be careful of is the page state. Things like the y
> cursor and margins that are currently setup in start_new_page may need
> to reinitialized when we move to an existing page.

Full ack. We deliberately ignored those things so far -- for example,
transactions give you no guarantees about your y position or any other
context but the ink on the page. Good call on the margins though.

If you or anyone else wanted to enumerate all of the page state bits
that make up a "context", that would help in more places than just
here.

Brad

Brad Ediger

unread,
Nov 5, 2009, 11:22:40 PM11/5/09
to prawn...@googlegroups.com
On Thu, Nov 5, 2009 at 10:15 PM, James Healy <ji...@deefa.com> wrote:
>
> Brad Ediger wrote:
>> > As usual, less magic in Prawn. Here's Greg's quick proof-of-concept
>> > code from back when we were hacking at LoneStar RubyConf:
>>
>> Oops, better link:
>>
>> http://gist.github.com/178054
>
> Wow, nice.
>
> One thing we need to be careful of is the page state. Things like the y
> cursor and margins that are currently setup in start_new_page may need
> to reinitialized when we move to an existing page.

Oh, and just to clarify, that code is about as bleeding-edge as it
gets. I had just merged my ObjectStore changes and Greg and I were
sitting in an airport talking about go_to_page, when he started typing
furiously and saying things like "Hey, I'll bet it would be as simple
as... Well what do you know!"

Gregory Brown

unread,
Nov 5, 2009, 11:51:29 PM11/5/09
to prawn...@googlegroups.com

I will probably sneak go_to_page into Prawn 0.6 as a private function
so as to enable page numbering.
Then we can debug it and think about how it ought to work in the real
sense for 0.7.

-greg

James Healy

unread,
Nov 7, 2009, 8:10:08 AM11/7/09
to prawn...@googlegroups.com
I've updated both the experimental branches on PDF::Reader and Prawn so
they now support significantly more documents.

As far as I can tell, *most* documents should work as templates. The
ObjectStore just starts at the source document's Root catalog and
recurses down the object graph, importing everything it finds. Any
objects not referred to by the object graph will not be imported.

There are a few classes of source document that will almost definitely
not work. Two that come to mind are encrypted files and files with
stream xref tables.

If anyone can find other documents that fail, please send me a copy
off list so I can check what's going wrong.

-- James Healy <ji...@deefa.com> Sun, 08 Nov 2009 00:04:46 +1100

Gregory Brown

unread,
Nov 7, 2009, 10:48:17 AM11/7/09
to prawn...@googlegroups.com
On Sat, Nov 7, 2009 at 8:10 AM, James Healy <ji...@deefa.com> wrote:
>
> I've updated both the experimental branches on PDF::Reader and Prawn so
> they now support significantly more documents.

This stuff sounds awesome. I'll give it a review after the 0.6
release, but maybe we can merge by 0.7.

-greg

Reply all
Reply to author
Forward
0 new messages