prawn gem: Problem with positioning the text - ruby

I'm using prawn gem to display a text in a pdf in two different positions and rotations as shown in the below image
I've managed to get the first one working but I couldn't able to get the second. Below is the image of what I got now
Here is the code
require "prawn"
Prawn::Document.generate("hello.pdf") do
text "{rquestID hashtag}", align: :left, valign: :left, rotate: -90
text "{rquestID hashtag}", align: :right, valign: :bottom, rotate: 90
end
Any help would be appreciated, Thanks!

I'm not sure why your code isn't producing the results you want, but you can use text_box to get around it, e.g.:
text_box "{rquestID hashtag}", align: :right, valign: :bottom, rotate: 90,
:width => 100, :height => 100, :at => [500, 100]
(You may have to play around with the numbers.)

Related

Ruby green_shoes styles not working

I am trying to use green shoes to create a GUI app to send people messages over LAN using Ruby and the Green Shoes(green_shoes) GUI library, but I am running into the issue of the .style function not working. I've worked with the original Shoes(red shoes) before and it has no issues. Here is the code for creation and style of the GUI:
Shoes.app(title: "Messenger", height: 150, width: 370, resizable: false) {
#creation
alert startMessage
#user_msg = para "Enter User"
#msgbox = para "Enter Message"
#user = edit_line
#msg = edit_line
#submit = button "Send"
#help = button "Send to PC"
#info = button "PC info"
#styles
#msg.style(:right => 5, :top => 57)
#user.style(:right => 5, :top => 25)
#user_msg.style(:left => 10, :top => 25)
#msgbox.style(:left => 10, :top => 57)
#submit.style(:left => 10, :bottom => 10)
#help.style(:left => 150, :bottom => 10)
#info.style(:right => 15, :bottom => 20)
#...
It is not that the styles "aren't working" but rather they are unsupported.
I see reference to right and bottom in shoes Source but not in green_shoes seems that positioning in green_shoes is from top and left always.
Green Shoes style:right
Note: Green Shoes doesn't support :right style.
Green Shoes style:bottom
Note: Green Shoes doesn't support :bottom style.
This is why Shoes3 works and green shoes doesn't.
You will have to alter all your locations to be :top and :left which isn't that uncommon in layout designers.
Can't Wait for Shoes4 to be a full release (even if it does require jruby)
Shoes4 does support bottom and right Source

Background image inside a stack in Ruby Shoes

I've been trying to set a background image to the stack but I can't get it to work, am I doing something wrong? Here's my code
Shoes.app(:width => 550,
:height => 450) do
#Main container so I don't have to deal with scroll
stack(:width => 550,
:height => 450,
:scroll => false) do
background(image("img/intro_bg.jpg"))
end
end
I'm trying to avoid the scroll bar to appear since the re-size property doesn't work at all :/
Assuming img/intro_bg.jpg exists, please change
background(image("img/intro_bg.jpg"))
to
background('img/intro_bg.jpg')

Controlling content flow with Prawn

Let's say we want to display a title on the first page that takes up the top half of the page. The bottom half of the page should then fill up with our article text, and the text should continue to flow over into the subsequent pages until it runs out:
This is a pretty basic layout scenario but I don't understand how one would implement it in Prawn.
Here's some example code derived from their online documentation:
pdf = Prawn::Document.new do
text "The Prince", :align => :center, :size => 48
text "Niccolò Machiavelli", :align => :center, :size => 20
move_down 42
column_box([0, cursor], :columns => 3, :width => bounds.width) do
text((<<-END.gsub(/\s+/, ' ') + "\n\n") * 20)
All the States and Governments by which men are or ever have been ruled,
have been and are either Republics or Princedoms. Princedoms are either
hereditary, in which the bla bla bla bla .....
END
end
end.render
but that will just continue to show the title space for every page:
What's the right way to do this?
I have been fighting with this same problem. I ended up subclassing ColumnBox and adding a helper to invoke it like so:
module Prawn
class Document
def reflow_column_box(*args, &block)
init_column_box(block) do |parent_box|
map_to_absolute!(args[0])
#bounding_box = ReflowColumnBox.new(self, parent_box, *args)
end
end
private
class ReflowColumnBox < ColumnBox
def move_past_bottom
#current_column = (#current_column + 1) % #columns
#document.y = #y
if 0 == #current_column
#y = #parent.absolute_top
#document.start_new_page
end
end
end
end
end
Then it is invoked exactly like a normal column box, but on the next page break will reflow to the parents bounding box. Change your line:
column_box([0, cursor], :columns => 3, :width => bounds.width) do
to
reflow_column_box([0, cursor], :columns => 3, :width => bounds.width) do
Hope it helps you. Prawn is pretty low level, which is a two-edged sword, it sometimes fails to do what you need, but the tools are there to extend and build more complicated structures.
I know this is old, but I thought I'd share that a new option has been added to fix this in v0.14.0.
:reflow_margins is an option that sets column boxes to fill their parent boxes on new page creation.
column_box(reflow_margins: true, columns: 3)
So, the column_box method creates a bounding box. The documented behavior of the bounding box is that it starts at the same position as on the previous page if it changes to the next page. So the behavior you are seeing is basically correct, also not what you want. The suggested workaround I have found by googling is to use a span instead, because spans do not have this behavior.
The problem now is, how to build text columns with spans? They don't seem to support spans natively. I tried to build a small script that mimicks columns with spans. It creates one span for each column and aligns them accordingly. Then, the text is written with text_box, which has the overflow: :truncate option. This makes the method return the text that did not fit in the text box, so that this text can then be rendered in the next column. The code probably needs some tweaking, but it should be enough to demonstrate how to do this.
require 'prawn'
text_to_write = ((<<-END.gsub(/\s+/, ' ') + "\n\n") * 20)
All the States and Governments by which men are or ever have been ruled,
have been and are either Republics or Princedoms. Princedoms are either
hereditary, in which the bla bla bla bla .....
END
pdf = Prawn::Document.generate("test.pdf") do
text "The Prince", :align => :center, :size => 48
text "Niccolò Machiavelli", :align => :center, :size => 20
move_down 42
starting_y = cursor
starting_page = page_number
span(bounds.width / 3, position: :left) do
text_to_write = text_box text_to_write, at: [bounds.left, 0], overflow: :truncate
end
go_to_page(starting_page)
move_cursor_to(starting_y)
span(bounds.width / 3, position: :center) do
text_to_write = text_box text_to_write, at: [bounds.left, 0], overflow: :truncate
end
go_to_page(starting_page)
move_cursor_to(starting_y)
span(bounds.width / 3, position: :right) do
text_box text_to_write, at: [bounds.left, 0]
end
end
I know this is not an ideal solution. However, this was the best I could come up with.
Use floats.
float do
span((bounds.width / 3) - 20, :position => :left) do
# Row Table Code
end
end
float do
span((bounds.width / 3) - 20, :position => :center) do
# Row Table Code
end
end
float do
span((bounds.width / 3) - 20, :position => :right) do
# Row Table Code
end
end
Use Prawns grid layout instead. It is very well documented...and easier to control your layout.

How do you add a border to an image with Prawn?

How can I add a border to an image with Prawn (pdf library)? If this is possible, can you add padding as well?
You can add a border using a bounding_box and stroke_bounds. In this example, I've put a border around an image. I've even given it padding of 15. It should be relatively easy to make this a function where a padding parameter could be used to calculate the difference between the image width and the bounding_box width.
require 'prawn'
Prawn::Document.generate("test.pdf") do
text "Boxed Image", :align=>:center, :size=>20
bounding_box([0, cursor], :width => 330) do
move_down 15
image "image.jpg", :fit => [300, 600], :position => :center
move_down 15
stroke_bounds
end
end

Watermarking with Prawn (using templates)

I need to be able to watermark a document that was created from a template. I have the following code right now:
# Note: the raw PDF text (body variable below) is sent from a remote server.
Prawn::Document.new(:template => StringIO.new(body), :page_size =>
'A4') do |document|
# ... including other pages and sections to the template here ...
# watermark
d.page_count.times do |i|
d.go_to_page i
d.stroke_line [d.bounds.left, d.bounds.bottom], [d.bounds.right, d.bounds.top]
d.draw_text "Watermark", :rotate => 45, :at => [100,100], :size => 100
end
end
This is ignoring the templated pages for some reason that I can't comprehend. Now here's where the plot thickens: if the server adds a watermark, then this code will work as expected (e.g. straight Ruby code = no overlaying text on the non-prawn-generated pages, yet watermarking works on a pre-watermarked template). My only guess is there is some way to create a z-index/layer that the server is doing but Prawn itself cannot.
Here is a portion of the code from the server that does the PDF
generation itself, this does the watermarking using iText:
PdfStamper stamper = new PdfStamper(...);
PdfContentByte over = stamper.GetOverContent(i + 1);
over.BeginText();
over.SetTextMatrix(20, 40);
over.SetFontAndSize(bf, 20);
over.SetColorFill(new Color(97, 150, 58));
over.ShowTextAligned(Element.ALIGN_CENTER,
watermarkText,
document.PageSize.Width / 2,
document.PageSize.Height / 2,
55);
over.EndText();
over.Stroke();
If that runs before I use the raw data in Prawn I can watermark, go
figure.
So my questions are:
Anyone know how I can achieve the same effect using prawn instead
of a hybrid? I'd rather handle the watermarking locally.
Is there a basic equivalent to GetOverContent() in Prawn?
Is there a better way to get a string of raw PDF data into Prawn
without using :template and StringIO? (I saw the #add_content method
but that didn't work)
TL;DR: I need to float text above the Prawn templated text a la
watermarking the document.
Any insight or paths I can research will be appreciated. If this
makes no sense I can clarify.
You could try stamping the document.
create_stamp("watermark") do
rotate(30, :origin => [-5, -5]) do
stroke_color "FF3333"
stroke_ellipse [0, 0], 29, 15
stroke_color "000000"
fill_color "993333"
font("Times-Roman") do
draw_text "Watermark", :at => [-23, -3]
end
fill_color "000000"
end
end
stamp_at "watermark", [210, 210]
create_stamp("stamp") do
fill_color "cc0000"
text_rendering_mode(:fill_stroke) do
transparent(0.5){
text_box "WATERMARK",
:size => 50,
:width => bounds.width,
:height => bounds.height,
:align => :center,
:valign => :center,
:at => [0, bounds.height],
:rotate => 45,
:rotate_around => :center
}
end
end
repeat (:all) do
stamp("stamp")
end

Resources