pdf-wrapper 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +6 -1
- data/Rakefile +1 -1
- data/examples/padded_image.rb +12 -0
- data/examples/template.rb +13 -0
- data/lib/pdf/wrapper.rb +69 -17
- data/specs/image_spec.rb +12 -1
- data/specs/spec_helper.rb +20 -5
- data/specs/wrapper_spec.rb +24 -1
- metadata +4 -2
data/CHANGELOG
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
v0.0.
|
1
|
+
v0.0.7 (30th April 2008)
|
2
|
+
- Added support for creating new pages from a template file (pdf/png/jpg/gif/svg/probably more)
|
3
|
+
- Convert the params to start_new_page to be an options hash
|
4
|
+
- Added a :padding option to PDF::Wrapper#image
|
5
|
+
|
6
|
+
v0.0.6 (28th April 2008)
|
2
7
|
- Fix a nasty bug in text layout code
|
3
8
|
|
4
9
|
v0.0.5 (27th April 2008)
|
data/Rakefile
CHANGED
@@ -0,0 +1,12 @@
|
|
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(:paper => :A4)
|
9
|
+
pdf.rectangle(100, 100, 200, 200)
|
10
|
+
pdf.image(File.dirname(__FILE__) + "/../specs/data/zits.gif", :left => 100, :top => 100, :width => 200, :height => 200, :padding => 25, :proportional => true)
|
11
|
+
|
12
|
+
pdf.render_to_file("image.pdf")
|
@@ -0,0 +1,13 @@
|
|
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(:paper => :A4)
|
9
|
+
pdf.default_font("Sans Serif")
|
10
|
+
pdf.default_color(:black)
|
11
|
+
pdf.text "James", :font => "Monospace", :font_size => 8, :alignment => :left
|
12
|
+
#pdf.start_new_page()
|
13
|
+
pdf.render_to_file("template.pdf")
|
data/lib/pdf/wrapper.rb
CHANGED
@@ -87,6 +87,9 @@ module PDF
|
|
87
87
|
# <tt>:margin_bottom</tt>:: The size of the default bottom margin (default 5% of page)
|
88
88
|
# <tt>:margin_left</tt>:: The size of the default left margin (default 5% of page)
|
89
89
|
# <tt>:margin_right</tt>:: The size of the default right margin (default 5% of page)
|
90
|
+
# <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.
|
91
|
+
# The page will be sized to match the template size. The use templates on subsequent pages, see the options for
|
92
|
+
# start_new_page.
|
90
93
|
def initialize(opts={})
|
91
94
|
|
92
95
|
# ensure we have recentish cairo bindings
|
@@ -99,7 +102,7 @@ module PDF
|
|
99
102
|
options.merge!(opts)
|
100
103
|
|
101
104
|
# test for invalid options
|
102
|
-
options.assert_valid_keys(:paper, :orientation, :background_color, :margin_left, :margin_right, :margin_top, :margin_bottom)
|
105
|
+
options.assert_valid_keys(:paper, :orientation, :background_color, :margin_left, :margin_right, :margin_top, :margin_bottom, :template)
|
103
106
|
options[:paper] = options[:paper].to_sym
|
104
107
|
raise ArgumentError, "Invalid paper option" unless PAGE_SIZES.include?(options[:paper])
|
105
108
|
|
@@ -139,6 +142,13 @@ module PDF
|
|
139
142
|
@page = 1
|
140
143
|
@repeating = []
|
141
144
|
|
145
|
+
# build the first page from a template if required
|
146
|
+
if opts[:template]
|
147
|
+
w, h = image_dimensions(opts[:template])
|
148
|
+
@surface.set_size(w, h)
|
149
|
+
image(opts[:template], :left => 0, :top => 0)
|
150
|
+
end
|
151
|
+
|
142
152
|
# move the cursor to the top left of the usable canvas
|
143
153
|
reset_cursor
|
144
154
|
end
|
@@ -503,8 +513,8 @@ module PDF
|
|
503
513
|
move_to(origx, origy)
|
504
514
|
end
|
505
515
|
|
506
|
-
# Adds a cubic Bezier spline to the path from the (x0, y0) to position (x3, y3)
|
507
|
-
# in user-space coordinates, using (x1, y1) and (x2, y2) as the control points.
|
516
|
+
# Adds a cubic Bezier spline to the path from the (x0, y0) to position (x3, y3)
|
517
|
+
# in user-space coordinates, using (x1, y1) and (x2, y2) as the control points.
|
508
518
|
# Options:
|
509
519
|
# <tt>:color</tt>:: The colour of the line
|
510
520
|
# <tt>:line_width</tt>:: The width of line. Defaults to 2.0
|
@@ -522,7 +532,7 @@ module PDF
|
|
522
532
|
# restore the cursor position
|
523
533
|
move_to(origx, origy)
|
524
534
|
end
|
525
|
-
|
535
|
+
|
526
536
|
|
527
537
|
# draw a rectangle starting at x,y with w,h dimensions.
|
528
538
|
# Parameters:
|
@@ -614,17 +624,22 @@ module PDF
|
|
614
624
|
# <tt>:height</tt>:: The height of the image
|
615
625
|
# <tt>:width</tt>:: The width of the image
|
616
626
|
# <tt>:proportional</tt>:: Boolean. Maintain image proportions when scaling. Defaults to false.
|
627
|
+
# <tt>:padding</tt>:: Add some padding between the image and the specified box.
|
617
628
|
#
|
618
629
|
# left and top default to the current cursor location
|
619
630
|
# width and height default to the size of the imported image
|
631
|
+
# padding defaults to 0
|
620
632
|
def image(filename, opts = {})
|
621
633
|
# TODO: add some options for justification and padding
|
622
|
-
# TODO: add a seperate method for adding arbitary pages from a PDF file to this one. Good for
|
623
|
-
# templating, etc. Save a letterhead as a PDF file, then open it and add it to the page
|
624
|
-
# as a starting point. Until we call start_new_page, we can add stuff over the top of the
|
625
|
-
# imported content
|
626
634
|
raise ArgumentError, "file #{filename} not found" unless File.file?(filename)
|
627
|
-
opts.assert_valid_keys(default_positioning_options.keys + [:proportional])
|
635
|
+
opts.assert_valid_keys(default_positioning_options.keys + [:padding, :proportional])
|
636
|
+
|
637
|
+
if opts[:padding]
|
638
|
+
opts[:left] += opts[:padding].to_i if opts[:left]
|
639
|
+
opts[:top] += opts[:padding].to_i if opts[:top]
|
640
|
+
opts[:width] -= opts[:padding].to_i * 2 if opts[:width]
|
641
|
+
opts[:height] -= opts[:padding].to_i * 2 if opts[:height]
|
642
|
+
end
|
628
643
|
|
629
644
|
case detect_image_type(filename)
|
630
645
|
when :pdf then draw_pdf filename, opts
|
@@ -712,14 +727,25 @@ module PDF
|
|
712
727
|
|
713
728
|
# move to the next page
|
714
729
|
#
|
715
|
-
#
|
716
|
-
# <tt
|
717
|
-
|
730
|
+
# options:
|
731
|
+
# <tt>:pageno</tt>:: If specified, the current page number will be set to that. By default, the page number will just increment.
|
732
|
+
# <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
|
733
|
+
def start_new_page(opts = {})
|
734
|
+
opts.assert_valid_keys(:pageno, :template)
|
735
|
+
|
718
736
|
@context.show_page
|
719
737
|
|
738
|
+
if opts[:template]
|
739
|
+
w, h = image_dimensions(opts[:template])
|
740
|
+
@surface.set_size(w, h)
|
741
|
+
image(opts[:template], :left => 0, :top => 0)
|
742
|
+
else
|
743
|
+
@surface.set_size(@page_width, @page_height)
|
744
|
+
end
|
745
|
+
|
720
746
|
# reset or increment the page counter
|
721
|
-
if pageno
|
722
|
-
@page = pageno.to_i
|
747
|
+
if opts[:pageno]
|
748
|
+
@page = opts[:pageno].to_i
|
723
749
|
else
|
724
750
|
@page += 1
|
725
751
|
end
|
@@ -977,6 +1003,32 @@ module PDF
|
|
977
1003
|
return y + row_height
|
978
1004
|
end
|
979
1005
|
|
1006
|
+
def image_dimensions(filename)
|
1007
|
+
raise ArgumentError, "file #{filename} not found" unless File.file?(filename)
|
1008
|
+
|
1009
|
+
case detect_image_type(filename)
|
1010
|
+
when :pdf then
|
1011
|
+
load_libpoppler
|
1012
|
+
page = Poppler::Document.new(filename).get_page(1)
|
1013
|
+
return page.size
|
1014
|
+
when :png then
|
1015
|
+
img_surface = Cairo::ImageSurface.from_png(filename)
|
1016
|
+
return img_surface.width, img_surface.height
|
1017
|
+
when :svg then
|
1018
|
+
load_librsvg
|
1019
|
+
handle = RSVG::Handle.new_from_file(filename)
|
1020
|
+
return handle.width, handle.height
|
1021
|
+
else
|
1022
|
+
load_libpixbuf
|
1023
|
+
begin
|
1024
|
+
pixbuf = Gdk::Pixbuf.new(filename)
|
1025
|
+
return pixbuf.width, pixbuf.height
|
1026
|
+
rescue Gdk::PixbufError
|
1027
|
+
raise ArgumentError, "Unrecognised image format (#{filename})"
|
1028
|
+
end
|
1029
|
+
end
|
1030
|
+
end
|
1031
|
+
|
980
1032
|
# load libpango if it isn't already loaded.
|
981
1033
|
# This will add some methods to the cairo Context class in addition to providing
|
982
1034
|
# its own classes and constants. A small amount of documentation is available at
|
@@ -1038,9 +1090,9 @@ module PDF
|
|
1038
1090
|
|
1039
1091
|
offset = 0
|
1040
1092
|
baseline = 0
|
1041
|
-
|
1093
|
+
|
1042
1094
|
iter = layout.iter
|
1043
|
-
loop do
|
1095
|
+
loop do
|
1044
1096
|
line = iter.line
|
1045
1097
|
ink_rect, logical_rect = iter.line_extents
|
1046
1098
|
if y + (baseline - offset) >= (y + h)
|
@@ -1065,7 +1117,7 @@ module PDF
|
|
1065
1117
|
@context.show_pango_layout_line(line)
|
1066
1118
|
|
1067
1119
|
break unless iter.next_line!
|
1068
|
-
end
|
1120
|
+
end
|
1069
1121
|
|
1070
1122
|
# return the y co-ord we finished on
|
1071
1123
|
return y + baseline - offset
|
data/specs/image_spec.rb
CHANGED
@@ -12,11 +12,22 @@ context "The PDF::Wrapper class" do
|
|
12
12
|
pdf.detect_image_type(File.dirname(__FILE__) + "/data/shipsail.jpg").should eql(:jpg)
|
13
13
|
end
|
14
14
|
|
15
|
-
specify "should be able to
|
15
|
+
specify "should be able to determine image dimensions correctly" do
|
16
|
+
pdf = PDF::Wrapper.new
|
17
|
+
pdf.image_dimensions(File.dirname(__FILE__) + "/data/google.png").should eql([166,55])
|
18
|
+
pdf.image_dimensions(File.dirname(__FILE__) + "/data/zits.gif").should eql([525,167])
|
19
|
+
pdf.image_dimensions(File.dirname(__FILE__) + "/data/orc.svg").should eql([734, 772])
|
20
|
+
pdf.image_dimensions(File.dirname(__FILE__) + "/data/utf8-long.pdf").map{ |d| d.to_i}.should eql([595,841])
|
21
|
+
pdf.image_dimensions(File.dirname(__FILE__) + "/data/shipsail.jpg").should eql([192,128])
|
22
|
+
end
|
23
|
+
|
24
|
+
specify "should be able to calculate scaled image dimensions correctly" do
|
16
25
|
pdf = PDF::Wrapper.new
|
17
26
|
pdf.calc_image_dimensions(100, 100, 200, 200).should eql([100.0,100.0])
|
18
27
|
pdf.calc_image_dimensions(nil, nil, 200, 200).should eql([200.0,200.0])
|
19
28
|
pdf.calc_image_dimensions(150, 200, 200, 200, true).should eql([150.0,150.0])
|
20
29
|
pdf.calc_image_dimensions(300, 250, 200, 200, true).should eql([250.0,250.0])
|
21
30
|
end
|
31
|
+
|
32
|
+
specify "should be able to draw an image with padding correctly"
|
22
33
|
end
|
data/specs/spec_helper.rb
CHANGED
@@ -14,20 +14,21 @@ require 'pdf/reader'
|
|
14
14
|
class PDF::Wrapper
|
15
15
|
public :build_pango_layout
|
16
16
|
public :calc_image_dimensions
|
17
|
-
public :load_librsvg
|
18
|
-
public :load_libpixbuf
|
19
|
-
public :load_libpango
|
20
|
-
public :load_libpoppler
|
21
17
|
public :default_text_options
|
22
18
|
public :detect_image_type
|
23
19
|
public :draw_pdf
|
24
20
|
public :draw_pixbuf
|
25
21
|
public :draw_png
|
26
22
|
public :draw_svg
|
23
|
+
public :image_dimensions
|
24
|
+
public :load_librsvg
|
25
|
+
public :load_libpixbuf
|
26
|
+
public :load_libpango
|
27
|
+
public :load_libpoppler
|
27
28
|
public :validate_color
|
28
29
|
end
|
29
30
|
|
30
|
-
# a helper class for
|
31
|
+
# a helper class for counting the number of pages in a PDF
|
31
32
|
class PageReceiver
|
32
33
|
attr_accessor :page_count
|
33
34
|
|
@@ -41,6 +42,20 @@ class PageReceiver
|
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
45
|
+
# a helper class for recording the dimensions of pages in a PDF
|
46
|
+
class PageSizeReceiver
|
47
|
+
attr_accessor :pages
|
48
|
+
|
49
|
+
def initialize
|
50
|
+
@pages = []
|
51
|
+
end
|
52
|
+
|
53
|
+
# Called when page parsing ends
|
54
|
+
def begin_page(args)
|
55
|
+
pages << args["MediaBox"] || args[:MediaBox]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
44
59
|
class PageTextReceiver
|
45
60
|
attr_accessor :content
|
46
61
|
|
data/specs/wrapper_spec.rb
CHANGED
@@ -399,7 +399,7 @@ context "The PDF::Wrapper class" do
|
|
399
399
|
pdf.page.should eql(1)
|
400
400
|
pdf.start_new_page
|
401
401
|
pdf.page.should eql(2)
|
402
|
-
pdf.start_new_page(50)
|
402
|
+
pdf.start_new_page(:pageno => 50)
|
403
403
|
pdf.page.should eql(50)
|
404
404
|
end
|
405
405
|
|
@@ -414,7 +414,30 @@ context "The PDF::Wrapper class" do
|
|
414
414
|
lambda { pdf.circle(100,100,100, :ponies => true)}.should raise_error(ArgumentError)
|
415
415
|
lambda { pdf.line(100,100,200,200, :ponies => true)}.should raise_error(ArgumentError)
|
416
416
|
lambda { pdf.rectangle(100,100,100,100, :ponies => true)}.should raise_error(ArgumentError)
|
417
|
+
lambda { pdf.start_new_page(:ponies => true)}.should raise_error(ArgumentError)
|
417
418
|
lambda { pdf.rounded_rectangle(100,100,100,100,10, :ponies => true)}.should raise_error(ArgumentError)
|
418
419
|
lambda { pdf.image(File.dirname(__FILE__) + "/data/orc.svg", :ponies => true)}.should raise_error(ArgumentError)
|
419
420
|
end
|
421
|
+
|
422
|
+
specify "should allow an existing file to be used as a template for page 1" do
|
423
|
+
pdf = PDF::Wrapper.new(:paper => :A4, :template => File.dirname(__FILE__) + "/data/orc.svg")
|
424
|
+
pdf.start_new_page
|
425
|
+
|
426
|
+
receiver = PageSizeReceiver.new
|
427
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
428
|
+
|
429
|
+
receiver.pages[0].should eql([0.0, 0.0, 734.0, 772.0])
|
430
|
+
receiver.pages[1].should eql([0.0, 0.0, 595.28, 841.89])
|
431
|
+
end
|
432
|
+
|
433
|
+
specify "should allow an existing file to be used as a template for page 2" do
|
434
|
+
pdf = PDF::Wrapper.new(:paper => :A4)
|
435
|
+
pdf.start_new_page(:template => File.dirname(__FILE__) + "/data/orc.svg")
|
436
|
+
|
437
|
+
receiver = PageSizeReceiver.new
|
438
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
439
|
+
|
440
|
+
receiver.pages[0].should eql([0.0, 0.0, 595.28, 841.89])
|
441
|
+
receiver.pages[1].should eql([0.0, 0.0, 734.0, 772.0])
|
442
|
+
end
|
420
443
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pdf-wrapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Healy
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-04-
|
12
|
+
date: 2008-04-30 00:00:00 +10:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -31,6 +31,8 @@ files:
|
|
31
31
|
- examples/table.rb
|
32
32
|
- examples/utf8-long.rb
|
33
33
|
- examples/utf8.rb
|
34
|
+
- examples/template.rb
|
35
|
+
- examples/padded_image.rb
|
34
36
|
- lib/pdf
|
35
37
|
- lib/pdf/core.rb
|
36
38
|
- lib/pdf/wrapper.rb
|