Repeater in Prawn PDF rendering contents twice - ruby-on-rails

I have a pdf being generated by prawn, it contains a header, a table and a footer. Both header and footer are repeatable, with :dynamic => true, the table is not.
The problem I'm having is that all content on the header and footer is displaying as if it's being rendered twice in the same place, and this seems to mess with the anti aliasing function so the text appears to be choppy and bold (see image below). However, when I zoom in or print it, it looks right.
Here's some code of the specific part where I start the repeater blocks:
pdf = Prawn::Document.new :page_size => "A4", :margin => [28, 20, 7, 20]
(...)
pdf.repeat :all, :dynamic => true do
pdf.bounding_box([0, 803], :width => 555, :height => 60) do
pdf.stroke_bounds
(...)
end
end
(...)
pdf.render
# End of file
As far as I know, this is the default way to declare a repeater block, I almost mirrorred it from the manual.
Here's the image: the top container is the header, inside the repeater, it looks like everything is bold, but it's the exact same font and line width as the section below, which is from the table, and looks fine. Sorry I can't post a larger part of the pdf, it's for confidentiality reasons.
If I remove the repeater, the header will look correct, as it should, but when I add it again it looks like this.
Has anyone else encountered this issue before? How do I fix it?
EDIT: Added some more code above. Also added the code below, which is inside a Rails template file, "historico.pdf.prawn", and this is how I call it on the controller to render the PDF and return it to the user:
rendered_pdf = render_to_string :template => "reports/historico.pdf"
send_data rendered_pdf, :filename => "Historico.pdf", :type => "application/pdf"

When you use pdf.repeat :all the pdf is 'reopened' after the document is already created and the data within the repeat block is added. This can cause a myriad of odd behavior, I believe this is what is causing your issue.
There is a related issue with a solution that utilizes Prawn's canvas method. If you adapt this solution to your problem (use canvas to generate your header and footer, rather than repeat :all) , you should no longer have these text-on-top-of-text problems.
Note:
It may be important for you to know that Prawn has officially stated that they are, "not in a good position to support templating features (I bring this up because you appear to be creating a template), " so similar workarounds may be needed if you continue to use this tool for these types of needs. Depending on your dependance on these types of templating features, you may want to look into using a different tool.

Related

render dynamic HTML with wicked pdf

I have a DSL that renders HTML. If I manually generate HTML in the console, and save it as a view (as an experiment, there's no reason to do this), so that it lives in app/views/manifests as show.pdf.erb, and then I simply render the PDF using Wicked's/Rails built in rendering, everything works great and looks great. Now, because this is dynamic HTML, meaning it can change based on the data, what I have to do is generate the HTML as a string, and then use Wicked's pdf_from_string:
html = HtmlGenerator.parse_node node, "root", #manifest
pdf = WickedPdf.new.pdf_from_string(html) # note, this is the same HTML that looks great as a view
and then send it to the browser
send_data(pdf,
:filename => "my_pdf_name.pdf",
:disposition => 'inline')
Now, everything is screwed up. It appears like the fonts are 15% bigger, all of my rows are screwed up. Does the rendering routine in WickedPDF use a different formatting that pdf_from_string?
Thanks for any help,
Kevin

Repeat HTML in every page generated with Wicked PDF and Rails

I'm generating PDF with the Wicked PDF gem on Ruby on Rails, but have to repeat some HTML content on every page.
What I'm trying is to use just part of the page to my main content, and use HTML to add stuff around it, in every page.
Something like this image (Check)
I tried playing with header, but I wasn't able to put the content in front of the HTML (even using z-index), and was only able to position the main content with margin and spacing vertically (didn't find any options to do it horizontally).
Any ideas? Thanks!
Since no one answered, I will post my solution here. It is not beautiful nor brilliant, it is so so so far from these - but since no one answered, maybe we can start a discussion from it.
I was able to generate a PDF with only the text (but with the correct margins), with no background, using Wicked PDF. Like this image. I used it to just save the file.
This was the code for it:
# Save PDF with only the text (with correct margins)
render :pdf => "text#{id}",
:margin => {:top => "1.6in", :left => "4.1in", :right => "1.2in", :bottom => "2.5in"},
:page_size => "Letter",
:template => "careers/job_pdf_text.pdf.erb",
:save_to_file => Rails.root.join('public/job_pdf_tempfiles', "text#{id}.pdf"),
:save_only => true,
:no_background => true
Then I used RMagick to create images from this saved PDF. The important here is that I saved GIFs with transparent background, and Magick creates one image for each page on the PDF. This was the code to save the images:
# Save images from the only-text PDF
#text_images = []
text_images_magick = Magick::Image.read(Rails.root.join('public/job_pdf_tempfiles', "text#{id}.pdf"))
text_images_magick.each_with_index do |image, index|
file_name = Rails.root.join('app/assets/images/careers_pdf', "text#{id}-#{index}.gif")
image.write(file_name)
#text_images << file_name
end
Ok, so at this moment I have images of the text, like this. Now what I did was put those in an HTML page, in the correct place and then used Wicked PDF again to render the final PDF. I rendered the PDF with margin 0, and for each #text_images I created a container, from which I positioned everything else (including the image itself) to achieve what I wanted in the beggining.
Does anyone have a better idea to share?

Forcing the inline rendering of a PDF document in Rails

I'm writing a service that generates PDF files from a set of XML files. The PDF is being correctly generated. However, everytime I click on the "view PDF" link, the browser asks the user to download the PDF file.
I need the PDF to display inline, just like any regular HTML page. I though I wrote the code right, but something must be missing - the browser keeps asking the user to download.
Here's the current code:
class PdfController < Controller
def generate
# stuff
send_data pdf_bytes, :disposition => 'inline', :type => 'application/pdf'
end
end
Any ideas?
Try removing the Content-Disposition header altogether. It's been my experience that Content-Disposition: attachment works pretty well, but many browsers have inconsistent behavior for any other value. If you want to display inline, it might just be better to remove the header and hope for the best. IE seems to have the most problems with this header. (Surprise, surprise.) Just make sure you're still setting Content-Type: application/pdf.
The other option would be to use an iframe and set the src of the iframe to your PDF file. Almost all browsers that support inline PDF viewing will handle this correctly. The downside is that you might end up displaying a blank iframe whereas non-supported browsers would have otherwise done a graceful fallback to simply downloading the PDF.

Multiple tables on one page with prawn

I'm using prawn for pdf generation and everything works quite well, but now I'm having a bit of a problem.
When I put multiple tables on one page, they just get put over each other and not under each other.
Is this normal behaviour and what can I do about it?
I add the tables on the most normal behaviour btw :)
Thanks!
What is the code you're using to create the PDF document with Prawn?
Without that, I'm guessing that you need to use 'bounding boxes' to seperate the different sections / tables in your document. Each bounding box is an area for content rendering, and new bounding boxes or text is rendered below that. See bounding_box() documentation or the example below:
> pdf.bounding_box([100,500], :width => 100, :height => 300) do
> pdf.text "This text will flow in a very narrow box starting" +
> "from [100,500]. The pointer will then be moved to [100,200]" +
> "and return to the margin_box"
> end

Can prawn generate PDFs with links?

I need to embed a link into a generated pdf in a ruby on rails app. Is there a way to do this with prawn?
Reading about this it turns out that prawn-format was the answer for awhile, but 0.7.x broke this.
prawn-format uses the link_annotate(rect, options={}) function to create links. What options need to be passed into this to get it to create a link in the PDF?
edit:
I would like to see a code example of this being done if anyone has one.
I know this is an old question, but for those still stumbling upon it, in current versions of Prawn, you can use inline format like this:
pdf.text "Website: <link href='http://www.stackoverflow.com'>stackoverflow</link>", :inline_format => true
If you are attempting to create a link to an external page (http://google.com), for instance you could use the following, to place a link that is 100x100 and placed at 5, 5 from the bottom left of the page, with a 1px border:
pdf.link_annotation([100, 100, 5, 5], :Border => [0,0,1], :A => { :Type => :Action, :S => :URI, :URI => Prawn::LiteralString.new("http://google.com") } )
Prawn Format would parse the text passed to the pdf.text method and find html a tags. It would then use regular expressions to parse out the target and link text and finally create a link like the one above with a bounding box (the first param) that would fit around the text that was within the tags. I'm not sure how you could achieve this without Prawn Format. But that is how you can create a link using link_annotation.
As of Prawn 0.7, prawn-format is
completely unsupported, and will not
work with versions of Prawn 0.7+. Feel
free to fork and fix, of course
- prawn-format's homepage on github
The other option is to use prawn's built in low-level annotation support:
http://prawn.majesticseacreature.com/docs/prawn-core/classes/Prawn/Document/Annotations.html#M000158
Heres the method:
link_annotation(rect, options={})
A convenience method for creating Link
annotations. rect must be an array of
four numbers, describing the bounds of
the annotation. The options hash
should include either :Dest
(describing the target destination,
usually as a string that has been
recorded in the document‘s Dests
tree), or :A (describing an action to
perform on clicking the link), or :PA
(for describing a URL to link to).
I recently did it like this - works great:
formatted_text_box([{:text=>"Google", :link=>"https://google.com", :color=>"0000ee"}])

Resources