pdf-wrapper 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,9 @@
1
- v0.0.6 (28th April 2008)w
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
@@ -6,7 +6,7 @@ require 'rake/testtask'
6
6
  require "rake/gempackagetask"
7
7
  require 'spec/rake/spectask'
8
8
 
9
- PKG_VERSION = "0.0.6"
9
+ PKG_VERSION = "0.0.7"
10
10
  PKG_NAME = "pdf-wrapper"
11
11
  PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
12
12
 
@@ -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")
@@ -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
- # arguments:
716
- # <tt>pageno</tt>:: If specified, the current page number will be set to that. By default, the page number will just increment.
717
- def start_new_page(pageno = nil)
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
@@ -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 calculate image dimensions correctly" do
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
@@ -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 couting the number of pages in a PDF
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
 
@@ -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.6
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-28 00:00:00 +10:00
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