pdf-wrapper 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +27 -0
- data/Rakefile +1 -1
- data/TODO +3 -1
- data/examples/cell.rb +2 -2
- data/examples/image.rb +4 -2
- data/examples/markup.rb +2 -2
- data/examples/repeating.rb +2 -2
- data/examples/scaled_image.rb +2 -2
- data/examples/shapes.rb +2 -2
- data/examples/table.rb +4 -6
- data/examples/table_fixed_col_width.rb +26 -0
- data/examples/translate.rb +2 -2
- data/examples/utf8-long.rb +3 -3
- data/examples/utf8.rb +2 -2
- data/examples/varied_page_size.rb +15 -0
- data/lib/pdf/wrapper.rb +158 -49
- data/lib/pdf/wrapper/table.rb +96 -21
- data/lib/pdf/wrapper/text.rb +52 -21
- data/specs/graphics_spec.rb +29 -26
- data/specs/image_spec.rb +21 -22
- data/specs/load_spec.rb +7 -6
- data/specs/spec_helper.rb +5 -0
- data/specs/tables_spec.rb +26 -25
- data/specs/text_spec.rb +72 -61
- data/specs/wrapper_spec.rb +162 -175
- metadata +4 -3
- data/examples/text.rb +0 -14
data/CHANGELOG
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
v0.2.0 (15th September 2008)
|
2
|
+
- API INCOMPATIBLE CHANGE: render() and render_file() are now deprecated.
|
3
|
+
- Use the output parameter of the constructor instead
|
4
|
+
- In versions before this, we automatically rendered to a StringIO object. This kept
|
5
|
+
things simple, but isn't great for scalability. Better to give the user the option
|
6
|
+
of bypassing memory and rendering direct to disk.
|
7
|
+
- Particuarly useful in rails apps to avoid the memory footprint of mongrels
|
8
|
+
blowing out
|
9
|
+
- Added Wrapper#open()
|
10
|
+
|
11
|
+
v0.1.5 (Unreleased)
|
12
|
+
- Fix text wrapping that crosses page boundaries
|
13
|
+
- when a new page is started as a result of a text() call, the text
|
14
|
+
should continue at the top of the next page, not the y value the
|
15
|
+
text started at
|
16
|
+
|
17
|
+
v0.1.4 (Unreleased)
|
18
|
+
- Wrapper#font_size now accepts a block for temporary font size changes
|
19
|
+
- Allow the page size to be changed when starting a new page
|
20
|
+
- Added support for manually setting table column widths
|
21
|
+
- prevents the column widths from growing or shrinking automatically
|
22
|
+
- Deprecated Table#table_options in favour of passing options to Table#new
|
23
|
+
- Thanks to Zubin Henner for the suggestion
|
24
|
+
- Deprecated Table#header_options and Table#headers= in favour of a new method
|
25
|
+
that can be used to specify both the content and options of the header row.
|
26
|
+
- Thanks to Zubin Henner for the suggestion
|
27
|
+
|
1
28
|
v0.1.3 (24th July 2008)
|
2
29
|
- Require the gem version of cairo
|
3
30
|
- >= 1.5. However I recommend >= 1.6.3 to avoid FATAL error under 1.8.7
|
data/Rakefile
CHANGED
data/TODO
CHANGED
data/examples/cell.rb
CHANGED
@@ -5,6 +5,6 @@ $:.unshift(File.dirname(__FILE__) + "/../lib")
|
|
5
5
|
|
6
6
|
require 'pdf/wrapper'
|
7
7
|
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
8
|
+
pdf = PDF::Wrapper.new("wrapper-cell.pdf", :paper => :A4)
|
9
9
|
pdf.cell("Given an index within a layout, determines the positions that of the strong and weak cursors if the insertion point is at that index. The position of each cursor is stored as a zero-width rectangle. The strong cursor location is the location where characters of the directionality equal to the base direction of the layout are inserted. The weak cursor location is the location where characters of the directionality opposite to the base direction of the layout are inserted.", 100, 100, 100, 200, {:border => "", :color => :black, :radius => 10})
|
10
|
-
pdf.
|
10
|
+
pdf.finish
|
data/examples/image.rb
CHANGED
@@ -5,12 +5,14 @@ $:.unshift(File.dirname(__FILE__) + "/../lib")
|
|
5
5
|
|
6
6
|
require 'pdf/wrapper'
|
7
7
|
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
8
|
+
pdf = PDF::Wrapper.new("image.pdf", :paper => :A4)
|
9
9
|
pdf.font("Sans Serif")
|
10
10
|
pdf.color(:black)
|
11
11
|
pdf.text("PDF::Wrapper Supports Images", :alignment => :center)
|
12
12
|
pdf.image(File.dirname(__FILE__) + "/../specs/data/zits.gif")
|
13
|
+
pdf.start_new_page
|
13
14
|
pdf.image(File.dirname(__FILE__) + "/../specs/data/google.png", :left => 100, :top => 350)
|
15
|
+
pdf.start_new_page
|
14
16
|
pdf.image(File.dirname(__FILE__) + "/../specs/data/stef.jpg", :left => 200, :top => 500)
|
15
17
|
pdf.start_new_page
|
16
18
|
pdf.image(File.dirname(__FILE__) + "/../specs/data/orc.svg", :left => pdf.margin_left, :top => pdf.margin_top, :width => pdf.body_width, :height => pdf.body_height)
|
@@ -18,4 +20,4 @@ pdf.start_new_page
|
|
18
20
|
pdf.image(File.dirname(__FILE__) + "/../specs/data/utf8-long.pdf", :left => pdf.margin_left, :top => pdf.margin_top, :width => pdf.body_width/2, :height => pdf.body_height/2)
|
19
21
|
pdf.color(:red)
|
20
22
|
|
21
|
-
pdf.
|
23
|
+
pdf.finish
|
data/examples/markup.rb
CHANGED
@@ -5,8 +5,8 @@ $:.unshift(File.dirname(__FILE__) + "/../lib")
|
|
5
5
|
|
6
6
|
require 'pdf/wrapper'
|
7
7
|
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
8
|
+
pdf = PDF::Wrapper.new("markup.pdf", :paper => :A4)
|
9
9
|
pdf.font("Sans Serif")
|
10
10
|
pdf.color(:black)
|
11
11
|
pdf.text "<i>James Healy</i>", :font => "Monospace", :font_size => 16, :alignment => :center, :markup => :pango
|
12
|
-
pdf.
|
12
|
+
pdf.finish
|
data/examples/repeating.rb
CHANGED
@@ -5,7 +5,7 @@ $:.unshift(File.dirname(__FILE__) + "/../lib")
|
|
5
5
|
|
6
6
|
require 'pdf/wrapper'
|
7
7
|
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
8
|
+
pdf = PDF::Wrapper.new("repeating.pdf", :paper => :A4)
|
9
9
|
|
10
10
|
pdf.repeating_element(:all) do
|
11
11
|
pdf.text("Page #{pdf.page}!", :left => pdf.margin_left, :top => pdf.margin_top, :font_size => 18, :alignment => :center)
|
@@ -35,4 +35,4 @@ pdf.start_new_page
|
|
35
35
|
pdf.start_new_page
|
36
36
|
pdf.start_new_page
|
37
37
|
|
38
|
-
pdf.
|
38
|
+
pdf.finish
|
data/examples/scaled_image.rb
CHANGED
@@ -5,10 +5,10 @@ $:.unshift(File.dirname(__FILE__) + "/../lib")
|
|
5
5
|
|
6
6
|
require 'pdf/wrapper'
|
7
7
|
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
8
|
+
pdf = PDF::Wrapper.new("scaled_image.pdf", :paper => :A4)
|
9
9
|
pdf.image(File.dirname(__FILE__) + "/../specs/data/zits.gif", :top => 100, :height => 200, :width => 200, :proportional => true, :center => true)
|
10
10
|
pdf.rectangle(pdf.margin_left, 100, 200, 200)
|
11
11
|
pdf.image(File.dirname(__FILE__) + "/../specs/data/windmill.jpg", :top => 400, :height => 200, :width => 200, :proportional => true, :center => true)
|
12
12
|
pdf.rectangle(pdf.margin_left, 400, 200, 200)
|
13
13
|
|
14
|
-
pdf.
|
14
|
+
pdf.finish
|
data/examples/shapes.rb
CHANGED
@@ -5,9 +5,9 @@ $:.unshift(File.dirname(__FILE__) + "/../lib")
|
|
5
5
|
|
6
6
|
require 'pdf/wrapper'
|
7
7
|
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
8
|
+
pdf = PDF::Wrapper.new("shapes.pdf", :paper => :A4)
|
9
9
|
pdf.rectangle(30,30,100,100, :fill_color => :red)
|
10
10
|
pdf.circle(100,300,30)
|
11
11
|
pdf.line(100, 350, 400, 150)
|
12
12
|
pdf.rectangle(300,300, 200, 200, :fill_color => :green, :radius => 10)
|
13
|
-
pdf.
|
13
|
+
pdf.finish
|
data/examples/table.rb
CHANGED
@@ -5,7 +5,7 @@ $:.unshift(File.dirname(__FILE__) + "/../lib")
|
|
5
5
|
|
6
6
|
require 'pdf/wrapper'
|
7
7
|
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
8
|
+
pdf = PDF::Wrapper.new("table.pdf", :paper => :A4)
|
9
9
|
pdf.text File.read(File.dirname(__FILE__) + "/../specs/data/utf8.txt").strip, :alignment => :centre
|
10
10
|
pdf.pad 5
|
11
11
|
headers = %w{one two three four}
|
@@ -20,11 +20,9 @@ data << [[], "j", "a", "m"]
|
|
20
20
|
data << %w{1 2 3 4}
|
21
21
|
end
|
22
22
|
|
23
|
-
table = PDF::Wrapper::Table.new do |t|
|
23
|
+
table = PDF::Wrapper::Table.new(:font_size => 10) do |t|
|
24
24
|
t.data = data
|
25
|
-
t.headers
|
26
|
-
t.table_options :font_size => 10
|
27
|
-
t.header_options :color => :white, :fill_color => :black
|
25
|
+
t.headers headers, {:color => :white, :fill_color => :black}
|
28
26
|
t.row_options 6, {:border => "t"}
|
29
27
|
t.row_options :even, {:fill_color => :gray}
|
30
28
|
t.col_options 0, {:border => "tb"}
|
@@ -36,4 +34,4 @@ table = PDF::Wrapper::Table.new do |t|
|
|
36
34
|
end
|
37
35
|
|
38
36
|
pdf.table(table)
|
39
|
-
pdf.
|
37
|
+
pdf.finish
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
5
|
+
|
6
|
+
require 'pdf/wrapper'
|
7
|
+
|
8
|
+
pdf = PDF::Wrapper.new("table-fixed.pdf", :paper => :A4)
|
9
|
+
pdf.text File.read(File.dirname(__FILE__) + "/../specs/data/utf8.txt").strip, :alignment => :centre
|
10
|
+
pdf.pad 5
|
11
|
+
headers = %w{one two three four}
|
12
|
+
|
13
|
+
data = []
|
14
|
+
data << ["This is some longer text to ensure...",2,3,4]
|
15
|
+
data << ["This is some longer text to ensure...",2,3,4]
|
16
|
+
|
17
|
+
table = PDF::Wrapper::Table.new do |t|
|
18
|
+
t.data = data
|
19
|
+
t.headers = headers
|
20
|
+
t.table_options :font_size => 10
|
21
|
+
t.header_options :color => :white, :fill_color => :black
|
22
|
+
t.manual_col_width [1,2,3], 25
|
23
|
+
end
|
24
|
+
|
25
|
+
pdf.table(table)
|
26
|
+
pdf.finish
|
data/examples/translate.rb
CHANGED
@@ -5,7 +5,7 @@ $:.unshift(File.dirname(__FILE__) + "/../lib")
|
|
5
5
|
|
6
6
|
require 'pdf/wrapper'
|
7
7
|
|
8
|
-
@pdf = PDF::Wrapper.new(:paper => :A4)
|
8
|
+
@pdf = PDF::Wrapper.new("translate.pdf", :paper => :A4)
|
9
9
|
|
10
10
|
def captioned_image(filename, caption, x, y)
|
11
11
|
@pdf.translate(x, y) do
|
@@ -18,4 +18,4 @@ captioned_image(File.dirname(__FILE__) + "/../specs/data/orc.svg", "One", 100, 1
|
|
18
18
|
captioned_image(File.dirname(__FILE__) + "/../specs/data/orc.svg", "Two", 250, 300)
|
19
19
|
captioned_image(File.dirname(__FILE__) + "/../specs/data/orc.svg", "Three", 400, 500)
|
20
20
|
|
21
|
-
@pdf.
|
21
|
+
@pdf.finish
|
data/examples/utf8-long.rb
CHANGED
@@ -5,7 +5,7 @@ $:.unshift(File.dirname(__FILE__) + "/../lib")
|
|
5
5
|
|
6
6
|
require 'pdf/wrapper'
|
7
7
|
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
8
|
+
pdf = PDF::Wrapper.new("utf8-long.pdf", :paper => :A4)
|
9
9
|
pdf.font("Sans Serif")
|
10
|
-
pdf.text File.read(File.dirname(__FILE__) + "/../specs/data/utf8-long.txt"), :font => "Monospace", :font_size => 8
|
11
|
-
pdf.
|
10
|
+
pdf.text File.read(File.dirname(__FILE__) + "/../specs/data/utf8-long.txt"), :font => "Monospace", :font_size => 8, :top => 300
|
11
|
+
pdf.finish
|
data/examples/utf8.rb
CHANGED
@@ -5,7 +5,7 @@ $:.unshift(File.dirname(__FILE__) + "/../lib")
|
|
5
5
|
|
6
6
|
require 'pdf/wrapper'
|
7
7
|
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
8
|
+
pdf = PDF::Wrapper.new("wrapper.pdf", :paper => :A4)
|
9
9
|
pdf.font("Sans Serif")
|
10
10
|
pdf.text File.read(File.dirname(__FILE__) + "/../specs/data/utf8.txt"), :font => "Monospace", :font_size => 8, :alignment => :center
|
11
|
-
pdf.
|
11
|
+
pdf.finish
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
5
|
+
|
6
|
+
require 'pdf/wrapper'
|
7
|
+
|
8
|
+
PDF::Wrapper.open("page_sizes.pdf", :paper => :A4) do |pdf|
|
9
|
+
pdf.rectangle(30,30,100,100, :fill_color => :red)
|
10
|
+
pdf.circle(100,300,30)
|
11
|
+
|
12
|
+
pdf.start_new_page(:orientation => :landscape)
|
13
|
+
pdf.line(100, 350, 400, 150)
|
14
|
+
pdf.rectangle(300,300, 200, 200, :fill_color => :green, :radius => 10)
|
15
|
+
end
|
data/lib/pdf/wrapper.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
require 'stringio'
|
4
4
|
require 'pdf/core'
|
5
5
|
require 'pdf/errors'
|
6
|
+
require 'tempfile'
|
7
|
+
require 'fileutils'
|
6
8
|
|
7
9
|
require File.dirname(__FILE__) + "/wrapper/graphics"
|
8
10
|
require File.dirname(__FILE__) + "/wrapper/images"
|
@@ -18,28 +20,49 @@ require 'cairo'
|
|
18
20
|
module PDF
|
19
21
|
# Create PDF files by using the cairo and pango libraries.
|
20
22
|
#
|
21
|
-
# Rendering to a file
|
23
|
+
# == Rendering to a file
|
22
24
|
#
|
23
25
|
# require 'pdf/wrapper'
|
24
|
-
# pdf = PDF::Wrapper.new(:paper => :A4)
|
26
|
+
# pdf = PDF::Wrapper.new("somefile.pdf", :paper => :A4)
|
25
27
|
# pdf.text "Hello World"
|
26
|
-
# pdf.
|
28
|
+
# pdf.finish
|
27
29
|
#
|
28
|
-
# Rendering to a
|
30
|
+
# == Rendering to a file (alternative)
|
29
31
|
#
|
30
32
|
# require 'pdf/wrapper'
|
31
|
-
# pdf
|
33
|
+
# File.open("somefile.pdf", "w") do |output|
|
34
|
+
# pdf = PDF::Wrapper.new(output, :paper => :A4)
|
35
|
+
# pdf.text "Hello World"
|
36
|
+
# pdf.finish
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# == Rendering to a string
|
40
|
+
#
|
41
|
+
# require 'pdf/wrapper'
|
42
|
+
# output = StringIO.new
|
43
|
+
# pdf = PDF::Wrapper.new(output, :paper => :A4)
|
32
44
|
# pdf.text "Hello World", :font_size => 16
|
33
|
-
#
|
45
|
+
# pdf.finish
|
46
|
+
# puts output.string
|
47
|
+
#
|
48
|
+
# == Block format
|
34
49
|
#
|
35
|
-
#
|
50
|
+
# Avoid the need to call finish()
|
36
51
|
#
|
37
52
|
# require 'pdf/wrapper'
|
38
|
-
#
|
53
|
+
# PDF::Wrapper.open("somefile.pdf", :paper => :A4)
|
54
|
+
# pdf.text "Hello World", :font_size => 16
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# == Changing the default font
|
58
|
+
#
|
59
|
+
# require 'pdf/wrapper'
|
60
|
+
# pdf = PDF::Wrapper.new("file.pdf", :paper => :A4)
|
39
61
|
# pdf.font("Monospace")
|
40
62
|
# pdf.text "Hello World", :font => "Sans Serif", :font_size => 18
|
41
63
|
# pdf.text "Pretend this is a code sample"
|
42
|
-
#
|
64
|
+
# pdf.finish
|
65
|
+
#
|
43
66
|
class Wrapper
|
44
67
|
|
45
68
|
attr_reader :page
|
@@ -74,6 +97,9 @@ module PDF
|
|
74
97
|
}
|
75
98
|
|
76
99
|
# create a new PDF::Wrapper class to compose a PDF document
|
100
|
+
# Params:
|
101
|
+
# <tt>output</tt>:: Where to render the PDF to. Can be a string containing a filename,
|
102
|
+
# or an IO object (File, StringIO, etc)
|
77
103
|
# Options:
|
78
104
|
# <tt>:paper</tt>:: The paper size to use (default :A4)
|
79
105
|
# <tt>:orientation</tt>:: :portrait (default) or :landscape
|
@@ -85,14 +111,14 @@ module PDF
|
|
85
111
|
# <tt>:template</tt>:: The path to an image file. If specified, the first page of the document will use the specified image as a template.
|
86
112
|
# The page will be sized to match the template size. The use templates on subsequent pages, see the options for
|
87
113
|
# start_new_page.
|
88
|
-
def initialize(
|
114
|
+
def initialize(*args)
|
89
115
|
# TODO: Investigate ways of using the cairo transform/translate/scale functionality to
|
90
116
|
# reduce the amount of irritating co-ordinate maths the user of PDF::Wrapper (ie. me!)
|
91
117
|
# is required to do.
|
92
118
|
# - translate the pdf body width so that it's 1.0 wide and 1.0 high?
|
93
119
|
# TODO: find a way to add metadata (title, author, subject, etc) to the output file
|
94
120
|
# currently no way to specify this in cairo.
|
95
|
-
# tentatively scheduled for cairo 1.
|
121
|
+
# tentatively scheduled for cairo 1.10 - see:
|
96
122
|
# - http://cairographics.org/roadmap/
|
97
123
|
# - http://lists.cairographics.org/archives/cairo/2007-September/011441.html
|
98
124
|
# - http://lists.freedesktop.org/archives/cairo/2006-April/006809.html
|
@@ -100,6 +126,25 @@ module PDF
|
|
100
126
|
# ensure we have recentish cairo bindings
|
101
127
|
raise "Ruby Cairo bindings version #{Cairo::BINDINGS_VERSION.join(".")} is too low. At least 1.5 is required" if Cairo::BINDINGS_VERSION.to_s < "150"
|
102
128
|
|
129
|
+
if args.size == 0
|
130
|
+
opts = {}
|
131
|
+
output = StringIO.new
|
132
|
+
warn "WARNING: deprecated call to PDF::Wrapper constructor. Check API documentation on new compulsory parameter"
|
133
|
+
elsif args.size == 1
|
134
|
+
if args.first.kind_of?(Hash)
|
135
|
+
opts = *args
|
136
|
+
output = StringIO.new
|
137
|
+
warn "WARNING: deprecated call to PDF::Wrapper constructor. Check API documentation on new compulsory parameter"
|
138
|
+
else
|
139
|
+
output = args.first
|
140
|
+
opts = {}
|
141
|
+
end
|
142
|
+
elsif args.size == 2
|
143
|
+
output, opts = *args
|
144
|
+
else
|
145
|
+
raise ArgumentError, 'Invalid parameters passed to constructor'
|
146
|
+
end
|
147
|
+
|
103
148
|
options = {:paper => :A4,
|
104
149
|
:orientation => :portrait,
|
105
150
|
:background_color => :white
|
@@ -107,20 +152,10 @@ module PDF
|
|
107
152
|
options.merge!(opts)
|
108
153
|
|
109
154
|
# test for invalid options
|
110
|
-
options.assert_valid_keys(:paper, :orientation, :background_color, :margin_left, :margin_right,
|
111
|
-
|
112
|
-
raise ArgumentError, "Invalid paper option" unless PAGE_SIZES.include?(options[:paper])
|
155
|
+
options.assert_valid_keys(:paper, :orientation, :background_color, :margin_left, :margin_right,
|
156
|
+
:margin_top, :margin_bottom, :io, :template)
|
113
157
|
|
114
|
-
|
115
|
-
if options[:orientation].eql?(:portrait)
|
116
|
-
@page_width = PAGE_SIZES[options[:paper]][0]
|
117
|
-
@page_height = PAGE_SIZES[options[:paper]][1]
|
118
|
-
elsif options[:orientation].eql?(:landscape)
|
119
|
-
@page_width = PAGE_SIZES[options[:paper]][1]
|
120
|
-
@page_height = PAGE_SIZES[options[:paper]][0]
|
121
|
-
else
|
122
|
-
raise ArgumentError, "Invalid orientation"
|
123
|
-
end
|
158
|
+
set_dimensions(options[:orientation], options[:paper])
|
124
159
|
|
125
160
|
# set page margins and dimensions of usable canvas
|
126
161
|
@margin_left = options[:margin_left] || (@page_width * 0.05).ceil
|
@@ -129,7 +164,7 @@ module PDF
|
|
129
164
|
@margin_bottom = options[:margin_bottom] || (@page_height * 0.05).ceil
|
130
165
|
|
131
166
|
# initialize some cairo objects to draw on
|
132
|
-
@output =
|
167
|
+
@output = output
|
133
168
|
@surface = Cairo::PDFSurface.new(@output, @page_width, @page_height)
|
134
169
|
@context = Cairo::Context.new(@surface)
|
135
170
|
|
@@ -158,6 +193,21 @@ module PDF
|
|
158
193
|
reset_cursor
|
159
194
|
end
|
160
195
|
|
196
|
+
# convenience method, takes the same arguments as the constructor along with a block,
|
197
|
+
# and automatically finishes the PDF for you.
|
198
|
+
#
|
199
|
+
#= Usage
|
200
|
+
#
|
201
|
+
# PDF::Wrapper.open("somefile.pdf") do |pdf|
|
202
|
+
# pdf.text "hi!"
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
def self.open(output, options = {}, &block)
|
206
|
+
pdf = PDF::Wrapper.new(output, options)
|
207
|
+
yield pdf
|
208
|
+
pdf.finish
|
209
|
+
end
|
210
|
+
|
161
211
|
#####################################################
|
162
212
|
# Functions relating to calculating various page dimensions
|
163
213
|
#####################################################
|
@@ -231,6 +281,14 @@ module PDF
|
|
231
281
|
@context.current_point
|
232
282
|
end
|
233
283
|
|
284
|
+
def x
|
285
|
+
@context.current_point.first
|
286
|
+
end
|
287
|
+
|
288
|
+
def y
|
289
|
+
@context.current_point.last
|
290
|
+
end
|
291
|
+
|
234
292
|
def margin_bottom
|
235
293
|
device_y_to_user_y(@margin_bottom).to_i
|
236
294
|
end
|
@@ -305,27 +363,30 @@ module PDF
|
|
305
363
|
|
306
364
|
# render the PDF and return it as a string
|
307
365
|
def render
|
308
|
-
#
|
309
|
-
#
|
366
|
+
# TODO: remove this method at some point. Deprecation started on 15th September 2008
|
367
|
+
warn "WARNING: render() is deprecated. See documentation for PDF::Wrapper#initialize for more information"
|
310
368
|
finish
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
render_file filename
|
369
|
+
case @output
|
370
|
+
when StringIO then return @output.string
|
371
|
+
when File then return File.read(@output.path)
|
372
|
+
else
|
373
|
+
return File.read(@output)
|
374
|
+
end
|
318
375
|
end
|
319
376
|
|
320
377
|
# save the rendered PDF to a file
|
321
378
|
def render_file(filename)
|
379
|
+
# TODO: remove this method at some point. Deprecation started on 15th September 2008
|
380
|
+
warn "WARNING: render_file() is deprecated. See documentation for PDF::Wrapper#initialize for more information"
|
322
381
|
finish
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
382
|
+
case @output
|
383
|
+
when StringIO then
|
384
|
+
File.open(filename, "w") do |of|
|
385
|
+
of.write(@output.string)
|
386
|
+
end
|
387
|
+
when File then return FileUtils.cp(@output.path, filename)
|
388
|
+
else
|
389
|
+
return FileUtils.cp(@output, filename)
|
329
390
|
end
|
330
391
|
end
|
331
392
|
|
@@ -449,13 +510,30 @@ module PDF
|
|
449
510
|
@context.move_to(margin_left,margin_top)
|
450
511
|
end
|
451
512
|
|
513
|
+
def finish
|
514
|
+
# finalise the document
|
515
|
+
@context.show_page
|
516
|
+
@context.target.finish
|
517
|
+
#@output.close if io_output?
|
518
|
+
@surface.finish
|
519
|
+
#@surface.destroy
|
520
|
+
#@context.destroy
|
521
|
+
self
|
522
|
+
rescue Cairo::SurfaceFinishedError
|
523
|
+
# do nothing, we're happy that the surfaced has been finished
|
524
|
+
end
|
525
|
+
|
452
526
|
# returns true if the PDF has already been rendered, false if it hasn't.
|
453
527
|
# Due to limitations of the underlying libraries, content cannot be
|
454
528
|
# added to a PDF once it has been rendered.
|
455
529
|
#
|
456
530
|
def finished?
|
457
|
-
|
458
|
-
|
531
|
+
if io_output?
|
532
|
+
@output.seek(@output.size - 6)
|
533
|
+
bytes = @output.read(6)
|
534
|
+
else
|
535
|
+
bytes = @output[-6,6]
|
536
|
+
end
|
459
537
|
bytes == "%%EOF\n" ? true : false
|
460
538
|
end
|
461
539
|
|
@@ -488,11 +566,15 @@ module PDF
|
|
488
566
|
# move to the next page
|
489
567
|
#
|
490
568
|
# options:
|
569
|
+
# <tt>:paper</tt>:: The paper size to use (default: same as the previous page)
|
570
|
+
# <tt>:orientation</tt>:: :portrait or :landscape (default: same as the previous page)
|
491
571
|
# <tt>:pageno</tt>:: If specified, the current page number will be set to that. By default, the page number will just increment.
|
492
572
|
# <tt>:template</tt>:: The path to an image file. If specified, the new page will use the specified image as a template. The page will be sized to match the template size
|
493
573
|
#
|
494
574
|
def start_new_page(opts = {})
|
495
|
-
opts.assert_valid_keys(:pageno, :template)
|
575
|
+
opts.assert_valid_keys(:paper, :orientation, :pageno, :template)
|
576
|
+
|
577
|
+
set_dimensions(opts[:orientation], opts[:paper])
|
496
578
|
|
497
579
|
@context.show_page
|
498
580
|
|
@@ -522,12 +604,31 @@ module PDF
|
|
522
604
|
|
523
605
|
private
|
524
606
|
|
525
|
-
def
|
526
|
-
#
|
527
|
-
@
|
528
|
-
@
|
529
|
-
|
530
|
-
#
|
607
|
+
def set_dimensions(orientation, paper)
|
608
|
+
# use the defaults if none were provided
|
609
|
+
orientation ||= @orientation
|
610
|
+
paper ||= @paper
|
611
|
+
|
612
|
+
# safety check
|
613
|
+
orientation = orientation.to_sym
|
614
|
+
paper = paper.to_sym
|
615
|
+
|
616
|
+
raise ArgumentError, "Unrecognised paper size (#{paper})" if PAGE_SIZES[paper].nil?
|
617
|
+
|
618
|
+
# set page dimensions
|
619
|
+
if orientation.eql?(:portrait)
|
620
|
+
@page_width = PAGE_SIZES[paper][0]
|
621
|
+
@page_height = PAGE_SIZES[paper][1]
|
622
|
+
elsif orientation.eql?(:landscape)
|
623
|
+
@page_width = PAGE_SIZES[paper][1]
|
624
|
+
@page_height = PAGE_SIZES[paper][0]
|
625
|
+
else
|
626
|
+
raise ArgumentError, "Invalid orientation"
|
627
|
+
end
|
628
|
+
|
629
|
+
# make the new values the defaults
|
630
|
+
@orientation = orientation
|
631
|
+
@paper = paper
|
531
632
|
end
|
532
633
|
|
533
634
|
# runs the code in block, passing it a hash of options that might be
|
@@ -557,6 +658,14 @@ module PDF
|
|
557
658
|
}
|
558
659
|
end
|
559
660
|
|
661
|
+
def io_output?
|
662
|
+
if @output.respond_to?(:write) && @output.respond_to?(:read)
|
663
|
+
true
|
664
|
+
else
|
665
|
+
false
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
560
669
|
# save and restore the cursor position around a block
|
561
670
|
def save_coords(&block)
|
562
671
|
origx, origy = current_point
|