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 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