Hacker News new | past | comments | ask | show | jobs | submit login
PDFs in Pure Ruby (majesticseacreature.com)
67 points by jmonegro on Jan 22, 2010 | hide | past | favorite | 46 comments



Without Prawn I probably wouldn't have been able to do the web version of my software in an acceptable amount of time. It is amazing software -- far superior to every other way I have found to render PDFs, and I come from Enterprise Java where that is practically a religious calling.

Incidentally, although this use is quite off-label: Prawn exposes a very nice API for drawing arbitrary geometrical objects. ImageMagick/GraphicsMagick can convert PDF files to image files in your favorite format. This means you can use prawn to draw, e.g., an org chart for about a fiftieth of the pain it would take to draw it using graphics primitives in ImageMagick or what have you.

That reminds me -- I tried to throw money at the developers and they requested I send it to Heifer International. Somebody is getting a cow because I didn't have one writing my print jobs.


I think that our users might appreciate a magick-prawn extension that allows Prawn::Document#to_svg (or other formats).

And also, thanks for donating!


I'd be happy to make you one, but it is literally one line of code after you generate the PDF. I think my commit message for that feature was "PDF -> GIF. I get paid for this!?"


I did a similar thing, actually, to render a successive series of Prawn documents (2-d scenes) into a Quicktime movie. Prawn -> series of pngs -> ffmpeg -> mov. It was a quick-and-dirty hack, but I was surprised by the simplicity.


Yeah, I guess it's easy enough to do on your own if you have RMagick handy. Good point.


RMagick leaks memory like a sieve. I do this in a pair of worker threads that just fire off system calls to the GraphicsMagick command. (Hat tip to HN: I learned about it here and saved 50% on conversion time versus doing it with ImageMagick.)


Ah, interesting. Yeah, I'm certainly aware of RMagick's memory issues, fortunately, haven't had a need for it.


We use Prawn to generate GitHub's PDF receipts and FI invoices, it's a great library.


Sweet. We're working on a rewrite of the table layout engine (github: bradediger/prawn-layout@refactor -- whoa, that is meta) so chime in if there's anything that seems missing from the current API. cheers.

[edit: fix github project reference]


Prawn is pretty neat, but what I'd really like to see is HTML to PDF in pure Ruby. I had to use a Java library wrapped in a Ruby module to do this. Complicates my server configuration (needs the JVM) more than I'd like.


I'm the maintainer of Prawn, and yeah, it'd be nice to see this. Jamis Buck tried this with prawn-format, but after a while we dropped support for it because it fell behind our core library and started breaking (Jamis had since moved on to other things).

In order for this to happen, what we really need is a solid box model. Since we don't have that yet, it's a very hard problem. If someone wanted to pay me to work on it full time for a year, I could get it built.

But failing that, we'll have to wait a good deal of time for this, unless someone else finds a large chunk of dedicated time for it.

Until then, Flying Saucer is the way to go if you can't afford PrinceXML price tag.


Agreed. That's what I ended up using and it's fantastic. Great CSS support and coupled with the TagSoup parser, you can convert almost anything.



That's just a wrapper over Prince XML, I ended up writing my own wrapper over Flying Saucer: https://xhtmlrenderer.dev.java.net/


You can try HTMLDOC (http://htmldoc.rubyforge.org/) which is a wrapper around a C library (I believe) that does exactly this. I've used it before, it's pretty fast and stable and you don't have to worry about JVM.


There are many webservices out there (paid and free) that do this for you. You might want to consider that instead.


Any details you can share? I may have a need of something similar.


The best way to do this is FlyingSaucer via JRuby.

https://xhtmlrenderer.dev.java.net/


I thought about that but I didn't want my entire app running within the JVM.


You probably wouldn't have to do that. Check into something like resque: http://github.com/defunkt/resque

(depends upon your needs, of course)


Yeah, I used Flying Saucer: https://xhtmlrenderer.dev.java.net/

Only, I needed to parse plain HTML (not just XHTML) so I'm using TagSoup as the replacement parser: http://home.ccil.org/~cowan/XML/tagsoup/

This combination is awesome.


http://pdf-render.heroku.com/ - here's hello world in Sinatra with prawn, to give you a sense of how fun it is to use :)

require 'rubygems' require 'sinatra' require 'prawn'

get '/' do "<h1>This is a simple pdf rendering webservice. GET <a href='/hello%20world.pdf'>/hello%20world.pdf</a> to get a pdf back!</h1>" end

get '/*' do content_type('application/pdf') headers['Cache-Control'] = "public, max-age=6000000000000000000"

  pdf = Prawn::Document.new
  pdf.text(params[:splat][0].gsub(/.pdf\z/,''))
  pdf.render
end


Sorry about that - http://pastie.org/789318


I am not a Ruby programmer so this might be a dumb question, but how does Prawn compare to Itext(Java)?


wc -l Print(ASTERIX_BORKS_HN).java #6 files, 1,800 lines

wc -l print_job.rb #1 file, 125 lines

This is not, strictly speaking, a fair comparison. In addition to being a superior version of everything the Java version does, the Ruby version also does GIF export, caching on the web server, and basic feature-wide analytics. The Java just barely staggers its way to generating a NxM grid and putting pleasingly aligned text in it. It is also littered with comments like:

// DO NOT EDIT. WILL NOT BE ABLE TO FIX. See r47 for what happened last time. (See r53.) (See r128.)

Do it in Prawn. I seriously have attempted to get my company to run a one-controller Rails app just to do PDF generation, because it would be cheaper going forward than the prodigious amount of effort we spend on report generation in Java. (This was, sadly, not approved.)


Prawn should run perfectly in JRuby, and will be officially supported by its 1.0 release. Sneak it in a .jar :)


I actually considered doing just that, for weeks. As much as I would have loved to do it, the Java application is a desktop app, and putting in JRuby would have added something like 15 MB to the installer.

I did propose that to work, though (we do generation on the server so the size doesn't matter), and we have done it if we had an acceptable supply of Ruby-speaking engineers. Bad news for them, good news for me: I would hate to have their business hobbled when I leave.


Itext is certainly more feature complete, but Prawn is pretty capable. It probably is more pleasant syntax-wise than iText, so for simple needs, Prawn might be better.

iText is almost certainly significantly faster, but I haven't benchmarked. If there are very cool low level features in iText that you'd like to see in Prawn, let us know on our mailing list.


While you're at it, check out this PDF creator in pure javascript:

http://code.google.com/p/jspdf/


Whoa! Awesome. Prawn is "fast for Ruby" but still not fast when compared to lower level implementations. How is performance here? (If it's decent, I'll definitely need to steal some ideas :)


I've been using prawn recently on a project, the only feature I'm missing is the ability to read its own output so I can compose operations independently.

It looks like it would be pretty difficult to add -- prawn is implemented as a clever DSL for writing postscript.


Prawn does not write postscript, it writes PDF. Though possibly similar in appearance, two different beasts, for sure.

And actually, we have support for reading arbitrary PDF on edge, expect a release in a few weeks :)

http://github.com/yob/prawn/tree/templates_2010


I use the soon-to-be integrated yob-templates_2010 fork to fill in existing PDF forms. All you have to do is add a ":template => filename" in "pdf = Prawn::Document.new()". You can also supply the template name to the prawn document instance after creating it: "pdf(:template => filename)". (see the prawn forum for details I posted there)


Some additional relevant links:

# source, wikis, bug tracker http://github.com/sandal/prawn

# mailing list http://groups.google.com/group/prawn-ruby

# my twitter account (I announce all Prawn releases and other stuff there -- mixed in with personal stuff)

http://twitter.com/seacreature


Please please please switch to Librelist :(


At least Google Groups doesn't expose your email address to the world, while it appears Librelist does (check out the archives here: http://librelist.com/browser/). If you're on a librelist list, you're asking to be spammed.


Get a proper spam filter. Your mail address probably is out there already.


I really consider it. Google Groups is a fucking nightmare.


Ok so another question for sandal. How do you begin to work on a pdf gen library in your favorite language? read the pdf standard?


This would be a good discussion for the Prawn mailing list. Post there and I'll reply with some details (and the other devs will likely chime in as well).

Just let us know what sort of feature set you want to implement, and we can point you to the relevant spec sections and supporting materials.

Prawn's source is pretty readable, and will be even more so as we refactor. A trip through the source might help, too:

http://github.com/sandal/prawn


The PDF spec is rather long but the basic format is simple enough. Check out http://yob.id.au/2009/11/12/intro-to-the-pdf-file-structure.... for a short intro.


There's also -require 'spreadsheet'- for generating .xls files on the fly:

http://spreadsheet.rubyforge.org/Spreadsheet.html


For generating PDFs with Ruby, Prince sure does look great, but it's a little high for my tastes!


So... am I old fashioned for using ERb and LaTex?


Don't worry, I do it too. I'll wait for the day when Prawn can compete with LaTeX's layouting :)


It never will. LaTeX is the right tool for layout, for now, at least. If someone wants to implement something like that on top of Prawn, awesome. But our goal isn't to be a layout tool, it's to provide all the low level tools necessary to implement PDF features to specification.

The difference is the toolchain. All you need to do to run Prawn is dump the files into your project.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: