pdf-wrapper 0.0.4 → 0.0.5
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 +9 -0
- data/Rakefile +3 -2
- data/TODO +1 -0
- data/examples/utf8.rb +1 -1
- data/lib/pdf/wrapper.rb +107 -27
- data/specs/image_spec.rb +22 -0
- data/specs/load_spec.rb +31 -0
- data/specs/shapes_spec.rb +194 -0
- data/specs/spec_helper.rb +70 -0
- data/specs/text_spec.rb +153 -0
- data/specs/wrapper_spec.rb +12 -397
- metadata +16 -11
data/CHANGELOG
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
v0.0.5 (27th April 2008)
|
2
|
+
- Fix crash when inserting multiple images
|
3
|
+
- added PDF::Wrapper#pad
|
4
|
+
- added PDF::Wrapper#text_width
|
5
|
+
- added support for customisable page margins (thanks to Paweł Kondzior)
|
6
|
+
- added support for cubic Bezier spline paths (thanks to Paweł Kondzior)
|
7
|
+
- added support for specifying the width of a cell border (thanks to Paweł Kondzior)
|
8
|
+
- fixed alignment of text (thanks to Paweł Kondzior)
|
9
|
+
|
1
10
|
v0.0.4 (12th March 2008)
|
2
11
|
- added support for custom line widths on primitive drawing shapes (circles,
|
3
12
|
lines, etc). Thanks Paweł Kondzior
|
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.
|
9
|
+
PKG_VERSION = "0.0.5"
|
10
10
|
PKG_NAME = "pdf-wrapper"
|
11
11
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
12
12
|
|
@@ -16,7 +16,8 @@ task :default => [ :spec ]
|
|
16
16
|
# run all rspecs
|
17
17
|
desc "Run all rspec files"
|
18
18
|
Spec::Rake::SpecTask.new("spec") do |t|
|
19
|
-
t.spec_files = FileList['specs
|
19
|
+
#t.spec_files = FileList['specs/**/*_spec.rb']
|
20
|
+
t.spec_files = ['specs/load_spec.rb','specs/image_spec.rb','specs/shapes_spec.rb','specs/text_spec.rb','specs/wrapper_spec.rb']
|
20
21
|
t.rcov = true
|
21
22
|
t.rcov_dir = (ENV['CC_BUILD_ARTIFACTS'] || 'doc') + "/rcov"
|
22
23
|
t.rcov_opts = ["--exclude","spec.*\.rb","--exclude",".*cairo.*","--exclude",".*rcov.*","--exclude",".*rspec.*","--exclude",".*pdf-reader.*"]
|
data/examples/utf8.rb
CHANGED
@@ -8,5 +8,5 @@ require 'pdf/wrapper'
|
|
8
8
|
pdf = PDF::Wrapper.new(:paper => :A4)
|
9
9
|
pdf.default_font("Sans Serif")
|
10
10
|
pdf.default_color(:black)
|
11
|
-
pdf.text File.read(File.dirname(__FILE__) + "/../specs/data/utf8.txt"), :font => "Monospace", :font_size => 8
|
11
|
+
pdf.text File.read(File.dirname(__FILE__) + "/../specs/data/utf8.txt"), :font => "Monospace", :font_size => 8, :alignment => :center
|
12
12
|
pdf.render_to_file("wrapper.pdf")
|
data/lib/pdf/wrapper.rb
CHANGED
@@ -83,7 +83,15 @@ module PDF
|
|
83
83
|
# <tt>:paper</tt>:: The paper size to use (default :A4)
|
84
84
|
# <tt>:orientation</tt>:: :portrait (default) or :landscape
|
85
85
|
# <tt>:background_color</tt>:: The background colour to use (default :white)
|
86
|
+
# <tt>:margin_top</tt>:: The size of the default top margin (default 5% of page)
|
87
|
+
# <tt>:margin_bottom</tt>:: The size of the default bottom margin (default 5% of page)
|
88
|
+
# <tt>:margin_left</tt>:: The size of the default left margin (default 5% of page)
|
89
|
+
# <tt>:margin_right</tt>:: The size of the default right margin (default 5% of page)
|
86
90
|
def initialize(opts={})
|
91
|
+
|
92
|
+
# ensure we have recentish cairo bindings
|
93
|
+
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"
|
94
|
+
|
87
95
|
options = {:paper => :A4,
|
88
96
|
:orientation => :portrait,
|
89
97
|
:background_color => :white
|
@@ -91,7 +99,8 @@ module PDF
|
|
91
99
|
options.merge!(opts)
|
92
100
|
|
93
101
|
# test for invalid options
|
94
|
-
options.assert_valid_keys(:paper, :orientation, :background_color)
|
102
|
+
options.assert_valid_keys(:paper, :orientation, :background_color, :margin_left, :margin_right, :margin_top, :margin_bottom)
|
103
|
+
options[:paper] = options[:paper].to_sym
|
95
104
|
raise ArgumentError, "Invalid paper option" unless PAGE_SIZES.include?(options[:paper])
|
96
105
|
|
97
106
|
# set page dimensions
|
@@ -106,11 +115,10 @@ module PDF
|
|
106
115
|
end
|
107
116
|
|
108
117
|
# set page margins and dimensions of usable canvas
|
109
|
-
|
110
|
-
@
|
111
|
-
@
|
112
|
-
@
|
113
|
-
@margin_bottom = (@page_height * 0.05).ceil
|
118
|
+
@margin_left = options[:margin_left] || (@page_width * 0.05).ceil
|
119
|
+
@margin_right = options[:margin_right] || (@page_width * 0.05).ceil
|
120
|
+
@margin_top = options[:margin_top] || (@page_height * 0.05).ceil
|
121
|
+
@margin_bottom = options[:margin_bottom] || (@page_height * 0.05).ceil
|
114
122
|
|
115
123
|
# initialize some cairo objects to draw on
|
116
124
|
@output = StringIO.new
|
@@ -265,7 +273,7 @@ module PDF
|
|
265
273
|
# <tt>:border</tt>:: Which sides of the cell should have a border? A string with any combination the letters tblr (top, bottom, left, right). Nil for no border, defaults to all sides.
|
266
274
|
# <tt>:border_width</tt>:: How wide should the border be?
|
267
275
|
# <tt>:border_color</tt>:: What color should the border be?
|
268
|
-
# <tt>:
|
276
|
+
# <tt>:fill_color</tt>:: A background color for the cell. Defaults to none.
|
269
277
|
# <tt>:padding</tt>:: The number of points to leave between the inside of the border and text. Defaults to 3.
|
270
278
|
def cell(str, x, y, w, h, opts={})
|
271
279
|
# TODO: add support for pango markup (see http://ruby-gnome2.sourceforge.jp/hiki.cgi?pango-markup)
|
@@ -274,12 +282,12 @@ module PDF
|
|
274
282
|
# TODO: add an option to draw a border with rounded corners
|
275
283
|
|
276
284
|
options = default_text_options
|
277
|
-
options.merge!({:border => "tblr", :border_width =>
|
285
|
+
options.merge!({:border => "tblr", :border_width => @default_line_width, :border_color => :black, :fill_color => nil, :padding => 3})
|
278
286
|
options.merge!(opts)
|
279
|
-
options.assert_valid_keys(default_text_options.keys + [:width, :border, :border_width, :border_color, :
|
287
|
+
options.assert_valid_keys(default_text_options.keys + [:width, :border, :border_width, :border_color, :fill_color, :padding])
|
280
288
|
|
281
289
|
# apply padding
|
282
|
-
textw =
|
290
|
+
textw = w - (options[:padding] * 2)
|
283
291
|
texth = h - (options[:padding] * 2)
|
284
292
|
textx = x + options[:padding]
|
285
293
|
texty = y + options[:padding]
|
@@ -291,7 +299,7 @@ module PDF
|
|
291
299
|
origx, origy = current_point
|
292
300
|
|
293
301
|
# TODO: raise an exception if the box coords or dimensions will place it off the canvas
|
294
|
-
rectangle(x,y,w,h, :color => options[:
|
302
|
+
rectangle(x,y,w,h, :color => options[:fill_color], :fill_color => options[:fill_color]) if options[:fill_color]
|
295
303
|
|
296
304
|
layout = build_pango_layout(str.to_s, textw, options)
|
297
305
|
|
@@ -301,11 +309,10 @@ module PDF
|
|
301
309
|
render_layout(layout, textx, texty, texth, :auto_new_page => false)
|
302
310
|
|
303
311
|
# draw a border around the cell
|
304
|
-
|
305
|
-
line(x,y,x+w,y, :color => options[:border_color])
|
306
|
-
line(x,y
|
307
|
-
line(x,y,x,y+h, :color => options[:border_color])
|
308
|
-
line(x+w,y,x+w,y+h, :color => options[:border_color]) if options[:border].include?("r")
|
312
|
+
line(x,y,x+w,y, :color => options[:border_color], :line_width => options[:border_width]) if options[:border].include?("t")
|
313
|
+
line(x,y+h,x+w,y+h, :color => options[:border_color], :line_width => options[:border_width]) if options[:border].include?("b")
|
314
|
+
line(x,y,x,y+h, :color => options[:border_color], :line_width => options[:border_width]) if options[:border].include?("l")
|
315
|
+
line(x+w,y,x+w,y+h, :color => options[:border_color], :line_width => options[:border_width]) if options[:border].include?("r")
|
309
316
|
|
310
317
|
# restore the cursor position
|
311
318
|
move_to(origx, origy)
|
@@ -421,6 +428,19 @@ module PDF
|
|
421
428
|
return height / Pango::SCALE
|
422
429
|
end
|
423
430
|
|
431
|
+
# Returns the amount of horizontal space needed to display the supplied text with the requested options
|
432
|
+
# opts is an options hash that specifies various attributes of the text. See the text function for more information.
|
433
|
+
# The text is assumed to not wrap.
|
434
|
+
def text_width(str, opts = {})
|
435
|
+
options = default_text_options.merge!(opts)
|
436
|
+
options.assert_valid_keys(default_text_options.keys)
|
437
|
+
|
438
|
+
layout = build_pango_layout(str.to_s, -1, options)
|
439
|
+
width, height = layout.size
|
440
|
+
|
441
|
+
return width / Pango::SCALE
|
442
|
+
end
|
443
|
+
|
424
444
|
#####################################################
|
425
445
|
# Functions relating to working with graphics
|
426
446
|
#####################################################
|
@@ -484,6 +504,27 @@ module PDF
|
|
484
504
|
move_to(origx, origy)
|
485
505
|
end
|
486
506
|
|
507
|
+
# Adds a cubic Bezier spline to the path from the (x0, y0) to position (x3, y3)
|
508
|
+
# in user-space coordinates, using (x1, y1) and (x2, y2) as the control points.
|
509
|
+
# Options:
|
510
|
+
# <tt>:color</tt>:: The colour of the line
|
511
|
+
# <tt>:line_width</tt>:: The width of line. Defaults to 2.0
|
512
|
+
def curve(x0, y0, x1, y1, x2, y2, x3, y3, opts = {})
|
513
|
+
options = {:color => @default_color, :line_width => @default_line_width }
|
514
|
+
options.merge!(opts)
|
515
|
+
options.assert_valid_keys(:color, :line_width)
|
516
|
+
origx, origy = current_point
|
517
|
+
|
518
|
+
set_color(options[:color])
|
519
|
+
@context.set_line_width(options[:line_width])
|
520
|
+
move_to(x0,y0)
|
521
|
+
@context.curve_to(x1, y1, x2, y2, x3, y3).stroke
|
522
|
+
|
523
|
+
# restore the cursor position
|
524
|
+
move_to(origx, origy)
|
525
|
+
end
|
526
|
+
|
527
|
+
|
487
528
|
# draw a rectangle starting at x,y with w,h dimensions.
|
488
529
|
# Parameters:
|
489
530
|
# <tt>:x</tt>:: The x co-ordinate of the top left of the rectangle.
|
@@ -630,6 +671,12 @@ module PDF
|
|
630
671
|
# Misc Functions
|
631
672
|
#####################################################
|
632
673
|
|
674
|
+
def pad(n)
|
675
|
+
x, y = current_point
|
676
|
+
move_to(x, y + n)
|
677
|
+
y + n
|
678
|
+
end
|
679
|
+
|
633
680
|
# move the cursor to an arbitary position on the current page
|
634
681
|
def move_to(x,y)
|
635
682
|
raise ArgumentError, 'x cannot be larger than the width of the page' if x > page_width
|
@@ -715,7 +762,11 @@ module PDF
|
|
715
762
|
# create a new Pango layout that our text will be added to
|
716
763
|
layout = @context.create_pango_layout
|
717
764
|
layout.text = str.to_s
|
718
|
-
|
765
|
+
if w == -1
|
766
|
+
layout.width = -1
|
767
|
+
else
|
768
|
+
layout.width = w * Pango::SCALE
|
769
|
+
end
|
719
770
|
layout.spacing = options[:spacing] * Pango::SCALE
|
720
771
|
|
721
772
|
# set the alignment of the text in the layout
|
@@ -830,7 +881,7 @@ module PDF
|
|
830
881
|
@context.scale(width / w, height / h)
|
831
882
|
@context.render_poppler_page(page)
|
832
883
|
end
|
833
|
-
move_to(x, y + height)
|
884
|
+
move_to(opts[:left] || x, (opts[:top] || y) + height)
|
834
885
|
end
|
835
886
|
|
836
887
|
def draw_pixbuf(filename, opts = {})
|
@@ -845,7 +896,7 @@ module PDF
|
|
845
896
|
@context.set_source_pixbuf(pixbuf, 0, 0)
|
846
897
|
@context.paint
|
847
898
|
end
|
848
|
-
move_to(x, y + height)
|
899
|
+
move_to(opts[:left] || x, (opts[:top] || y) + height)
|
849
900
|
end
|
850
901
|
|
851
902
|
def draw_png(filename, opts = {})
|
@@ -859,7 +910,7 @@ module PDF
|
|
859
910
|
@context.set_source(img_surface, 0, 0)
|
860
911
|
@context.paint
|
861
912
|
end
|
862
|
-
move_to(x, y + height)
|
913
|
+
move_to(opts[:left] || x, (opts[:top] || y) + height)
|
863
914
|
end
|
864
915
|
|
865
916
|
def draw_svg(filename, opts = {})
|
@@ -874,7 +925,7 @@ module PDF
|
|
874
925
|
@context.render_rsvg_handle(handle)
|
875
926
|
#@context.paint
|
876
927
|
end
|
877
|
-
move_to(x, y + height)
|
928
|
+
move_to(opts[:left] || x, (opts[:top] || y) + height)
|
878
929
|
end
|
879
930
|
|
880
931
|
# adds a single table row to the canvas. Top left of the row will be at the current x,y
|
@@ -990,11 +1041,35 @@ module PDF
|
|
990
1041
|
# adding text at the same co-ords
|
991
1042
|
orig_x = x
|
992
1043
|
orig_y = y
|
993
|
-
|
994
1044
|
# for each line in the layout
|
995
|
-
layout.
|
996
|
-
|
997
|
-
|
1045
|
+
# layout.alignment = Pango::Layout::ALIGN_RIGHT
|
1046
|
+
# layout.lines.each do |line|
|
1047
|
+
# #calculate where the next line starts
|
1048
|
+
# ink_rect, logical_rect = line.extents
|
1049
|
+
# y = y + (logical_rect.height / Pango::SCALE * (3.0/4.0)) + 1
|
1050
|
+
# if y >= (orig_y + h)
|
1051
|
+
# # our text is using the maximum amount of vertical space we want it to
|
1052
|
+
# if options[:auto_new_page]
|
1053
|
+
# # create a new page and we can continue adding text
|
1054
|
+
# start_new_page
|
1055
|
+
# x = orig_x
|
1056
|
+
# y = orig_y
|
1057
|
+
# else
|
1058
|
+
# # the user doesn't want us to continue on the next page, so
|
1059
|
+
# # stop adding lines to the canvas
|
1060
|
+
# break
|
1061
|
+
# end
|
1062
|
+
# end
|
1063
|
+
#
|
1064
|
+
# # move to the start of the next line
|
1065
|
+
# move_to(x, y)
|
1066
|
+
# # draw the line on the canvas
|
1067
|
+
# @context.show_pango_layout_line(line)
|
1068
|
+
# end
|
1069
|
+
iter = layout.iter
|
1070
|
+
loop do
|
1071
|
+
line = iter.line
|
1072
|
+
ink_rect, logical_rect = iter.line_extents
|
998
1073
|
y = y + (logical_rect.height / Pango::SCALE * (3.0/4.0)) + 1
|
999
1074
|
if y >= (orig_y + h)
|
1000
1075
|
# our text is using the maximum amount of vertical space we want it to
|
@@ -1011,10 +1086,15 @@ module PDF
|
|
1011
1086
|
end
|
1012
1087
|
|
1013
1088
|
# move to the start of the next line
|
1014
|
-
move_to(x, y)
|
1089
|
+
#move_to(x, y)
|
1090
|
+
baseline = iter.baseline / Pango::SCALE
|
1091
|
+
@context.move_to(x + logical_rect.x / Pango::SCALE, y + baseline)
|
1092
|
+
|
1015
1093
|
# draw the line on the canvas
|
1016
1094
|
@context.show_pango_layout_line(line)
|
1017
|
-
|
1095
|
+
|
1096
|
+
break unless iter.next_line!
|
1097
|
+
end
|
1018
1098
|
|
1019
1099
|
# return the y co-ord we finished on
|
1020
1100
|
return y
|
data/specs/image_spec.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
4
|
+
|
5
|
+
context "The PDF::Wrapper class" do
|
6
|
+
specify "should be able to detect the filetype of an image" do
|
7
|
+
pdf = PDF::Wrapper.new
|
8
|
+
pdf.detect_image_type(File.dirname(__FILE__) + "/data/google.png").should eql(:png)
|
9
|
+
pdf.detect_image_type(File.dirname(__FILE__) + "/data/zits.gif").should eql(:gif)
|
10
|
+
pdf.detect_image_type(File.dirname(__FILE__) + "/data/orc.svg").should eql(:svg)
|
11
|
+
pdf.detect_image_type(File.dirname(__FILE__) + "/data/utf8-long.pdf").should eql(:pdf)
|
12
|
+
pdf.detect_image_type(File.dirname(__FILE__) + "/data/shipsail.jpg").should eql(:jpg)
|
13
|
+
end
|
14
|
+
|
15
|
+
specify "should be able to calculate image dimensions correctly" do
|
16
|
+
pdf = PDF::Wrapper.new
|
17
|
+
pdf.calc_image_dimensions(100, 100, 200, 200).should eql([100.0,100.0])
|
18
|
+
pdf.calc_image_dimensions(nil, nil, 200, 200).should eql([200.0,200.0])
|
19
|
+
pdf.calc_image_dimensions(150, 200, 200, 200, true).should eql([150.0,150.0])
|
20
|
+
pdf.calc_image_dimensions(300, 250, 200, 200, true).should eql([250.0,250.0])
|
21
|
+
end
|
22
|
+
end
|
data/specs/load_spec.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
4
|
+
|
5
|
+
context "The PDF::Wrapper class" do
|
6
|
+
specify "should load external libs correctly" do
|
7
|
+
pdf = PDF::Wrapper.new
|
8
|
+
|
9
|
+
# lib gdkpixbuf
|
10
|
+
::Object.const_defined?(:Gdk).should eql(false)
|
11
|
+
pdf.load_libpixbuf
|
12
|
+
::Object.const_defined?(:Gdk).should eql(true)
|
13
|
+
::Gdk.const_defined?(:Pixbuf).should eql(true)
|
14
|
+
|
15
|
+
# pango
|
16
|
+
::Object.const_defined?(:Pango).should eql(false)
|
17
|
+
pdf.load_libpango
|
18
|
+
::Object.const_defined?(:Pango).should eql(true)
|
19
|
+
|
20
|
+
# libpoppler
|
21
|
+
::Object.const_defined?(:Poppler).should eql(false)
|
22
|
+
pdf.load_libpoppler
|
23
|
+
::Object.const_defined?(:Poppler).should eql(true)
|
24
|
+
|
25
|
+
# librsvg
|
26
|
+
::Object.const_defined?(:RSVG).should eql(false)
|
27
|
+
pdf.load_librsvg
|
28
|
+
::Object.const_defined?(:RSVG).should eql(true)
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
4
|
+
|
5
|
+
context "The PDF::Wrapper class" do
|
6
|
+
specify "should be able to draw a single line onto the canvas" do
|
7
|
+
x0 = y0 = 100
|
8
|
+
x1 = y1 = 200
|
9
|
+
pdf = PDF::Wrapper.new
|
10
|
+
pdf.line(x0,y0,x1,y1)
|
11
|
+
|
12
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
13
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
14
|
+
|
15
|
+
# the begin_new_subpath command specifies the start of the line, append line specifies the end
|
16
|
+
receiver.count(:begin_new_subpath).should eql(1)
|
17
|
+
receiver.count(:append_line).should eql(1)
|
18
|
+
receiver.first_occurance_of(:begin_new_subpath)[:args].should eql([x0.to_f, 741.89])
|
19
|
+
receiver.first_occurance_of(:append_line)[:args].should eql([x1.to_f, 641.89])
|
20
|
+
end
|
21
|
+
|
22
|
+
specify "should be able to draw a single line onto the canvas with a width of 5" do
|
23
|
+
x0 = y0 = 100
|
24
|
+
x1 = y1 = 200
|
25
|
+
width = 5
|
26
|
+
pdf = PDF::Wrapper.new
|
27
|
+
pdf.line(x0,y0,x1,y1, :line_width => width)
|
28
|
+
|
29
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
30
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
31
|
+
|
32
|
+
# the begin_new_subpath command specifies the start of the line, append line specifies the end
|
33
|
+
receiver.count(:set_line_width).should eql(1)
|
34
|
+
receiver.count(:begin_new_subpath).should eql(1)
|
35
|
+
receiver.count(:append_line).should eql(1)
|
36
|
+
receiver.first_occurance_of(:set_line_width)[:args].should eql([width.to_f])
|
37
|
+
receiver.first_occurance_of(:begin_new_subpath)[:args].should eql([x0.to_f, 741.89])
|
38
|
+
receiver.first_occurance_of(:append_line)[:args].should eql([x1.to_f, 641.89])
|
39
|
+
end
|
40
|
+
|
41
|
+
specify "should be able to draw a cubic bezier spline onto the canvas"
|
42
|
+
|
43
|
+
specify "should be able to draw an empty rectangle onto the canvas" do
|
44
|
+
x = y = 100
|
45
|
+
w = h = 200
|
46
|
+
pdf = PDF::Wrapper.new
|
47
|
+
pdf.rectangle(x,y,w,h)
|
48
|
+
|
49
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
50
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
51
|
+
|
52
|
+
# the begin_new_subpath command specifies the start of the line, append line specifies the end
|
53
|
+
callbacks = receiver.all(:append_rectangle)
|
54
|
+
callbacks.size.should eql(2)
|
55
|
+
# don't care about the first rectangel, it just goes around the outside of the page
|
56
|
+
callbacks.shift
|
57
|
+
callbacks.shift[:args].should eql([100.0, 741.89, 200.0, -200.0])
|
58
|
+
end
|
59
|
+
|
60
|
+
specify "should be able to draw an empty rectangle onto the canvas with a line width of 5" do
|
61
|
+
x = y = 100
|
62
|
+
w = h = 200
|
63
|
+
width = 5
|
64
|
+
pdf = PDF::Wrapper.new
|
65
|
+
pdf.rectangle(x,y,w,h, :line_width => width)
|
66
|
+
|
67
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
68
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
69
|
+
|
70
|
+
# ensure the line width was set correctly
|
71
|
+
receiver.count(:set_line_width).should eql(1)
|
72
|
+
receiver.first_occurance_of(:set_line_width)[:args].should eql([width.to_f])
|
73
|
+
|
74
|
+
# the begin_new_subpath command specifies the start of the line, append line specifies the end
|
75
|
+
callbacks = receiver.all(:append_rectangle)
|
76
|
+
callbacks.size.should eql(2)
|
77
|
+
# don't care about the first rectangel, it just goes around the outside of the page
|
78
|
+
callbacks.shift
|
79
|
+
callbacks.shift[:args].should eql([100.0, 741.89, 200.0, -200.0])
|
80
|
+
end
|
81
|
+
|
82
|
+
specify "should be able to draw a filled rectangle onto the canvas"
|
83
|
+
=begin
|
84
|
+
do
|
85
|
+
x = y = 100
|
86
|
+
w = h = 200
|
87
|
+
pdf = PDF::Wrapper.new
|
88
|
+
pdf.rectangle(x,y,w,h, :fill_color => :red)
|
89
|
+
|
90
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
91
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
92
|
+
|
93
|
+
# TODO: test for the appropriate pattern of callbacks
|
94
|
+
end
|
95
|
+
=end
|
96
|
+
|
97
|
+
specify "should be able to draw an empty rounded rectangle onto the canvas"
|
98
|
+
=begin
|
99
|
+
do
|
100
|
+
x = y = 100
|
101
|
+
w = h = 200
|
102
|
+
r = 5
|
103
|
+
pdf = PDF::Wrapper.new
|
104
|
+
pdf.rounded_rectangle(x,y,w,h,r)
|
105
|
+
|
106
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
107
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
108
|
+
|
109
|
+
# TODO: test for the appropriate pattern of callbacks
|
110
|
+
end
|
111
|
+
=end
|
112
|
+
|
113
|
+
specify "should be able to draw an empty rounded rectangle onto the canvas with a line width of 5"
|
114
|
+
=begin
|
115
|
+
do
|
116
|
+
x = y = 100
|
117
|
+
w = h = 200
|
118
|
+
r = 5
|
119
|
+
w = 5
|
120
|
+
pdf = PDF::Wrapper.new
|
121
|
+
pdf.rounded_rectangle(x,y,w,h,r, :line_width => w)
|
122
|
+
|
123
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
124
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
125
|
+
|
126
|
+
# TODO: test for the appropriate pattern of callbacks
|
127
|
+
end
|
128
|
+
=end
|
129
|
+
|
130
|
+
specify "should be able to draw a filled rounded rectangle onto the canvas"
|
131
|
+
=begin
|
132
|
+
do
|
133
|
+
x = y = 100
|
134
|
+
w = h = 200
|
135
|
+
r = 5
|
136
|
+
pdf = PDF::Wrapper.new
|
137
|
+
pdf.rounded_rectangle(x,y,w,h,r, :fill_color => :red)
|
138
|
+
|
139
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
140
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
141
|
+
|
142
|
+
# TODO: test for the appropriate pattern of callbacks
|
143
|
+
end
|
144
|
+
=end
|
145
|
+
|
146
|
+
specify "should be able to draw an empty circle onto the canvas"
|
147
|
+
=begin
|
148
|
+
do
|
149
|
+
x = 100
|
150
|
+
y = 200
|
151
|
+
r = 5
|
152
|
+
pdf = PDF::Wrapper.new
|
153
|
+
pdf.circle(x,y,r)
|
154
|
+
|
155
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
156
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
157
|
+
|
158
|
+
# TODO: test for the appropriate pattern of callbacks
|
159
|
+
end
|
160
|
+
=end
|
161
|
+
|
162
|
+
specify "should be able to draw an empty circle onto the canvas with a line width of 5"
|
163
|
+
=begin
|
164
|
+
do
|
165
|
+
x = 100
|
166
|
+
y = 200
|
167
|
+
r = 5
|
168
|
+
w = 5
|
169
|
+
pdf = PDF::Wrapper.new
|
170
|
+
pdf.circle(x,y,r, :line_width => w)
|
171
|
+
|
172
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
173
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
174
|
+
|
175
|
+
# TODO: test for the appropriate pattern of callbacks
|
176
|
+
end
|
177
|
+
=end
|
178
|
+
|
179
|
+
specify "should be able to draw a filled circle onto the canvas"
|
180
|
+
=begin
|
181
|
+
do
|
182
|
+
x = 100
|
183
|
+
y = 200
|
184
|
+
r = 5
|
185
|
+
pdf = PDF::Wrapper.new
|
186
|
+
pdf.circle(x,y,r, :fill_color => :red)
|
187
|
+
|
188
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
189
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
190
|
+
|
191
|
+
# TODO: test for the appropriate pattern of callbacks
|
192
|
+
end
|
193
|
+
=end
|
194
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
|
4
|
+
|
5
|
+
require 'pdf/wrapper'
|
6
|
+
require 'tempfile'
|
7
|
+
require 'rubygems'
|
8
|
+
|
9
|
+
gem "pdf-reader", ">=0.6.1"
|
10
|
+
|
11
|
+
require 'pdf/reader'
|
12
|
+
|
13
|
+
# make some private methods of PDF::Wrapper public for testing
|
14
|
+
class PDF::Wrapper
|
15
|
+
public :build_pango_layout
|
16
|
+
public :calc_image_dimensions
|
17
|
+
public :load_librsvg
|
18
|
+
public :load_libpixbuf
|
19
|
+
public :load_libpango
|
20
|
+
public :load_libpoppler
|
21
|
+
public :default_text_options
|
22
|
+
public :detect_image_type
|
23
|
+
public :draw_pdf
|
24
|
+
public :draw_pixbuf
|
25
|
+
public :draw_png
|
26
|
+
public :draw_svg
|
27
|
+
public :validate_color
|
28
|
+
end
|
29
|
+
|
30
|
+
# a helper class for couting the number of pages in a PDF
|
31
|
+
class PageReceiver
|
32
|
+
attr_accessor :page_count
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@page_count = 0
|
36
|
+
end
|
37
|
+
|
38
|
+
# Called when page parsing ends
|
39
|
+
def end_page
|
40
|
+
@page_count += 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class PageTextReceiver
|
45
|
+
attr_accessor :content
|
46
|
+
|
47
|
+
def initialize
|
48
|
+
@content = []
|
49
|
+
end
|
50
|
+
|
51
|
+
# Called when page parsing starts
|
52
|
+
def begin_page(arg = nil)
|
53
|
+
@content << ""
|
54
|
+
end
|
55
|
+
|
56
|
+
def show_text(string, *params)
|
57
|
+
@content.last << string.strip
|
58
|
+
end
|
59
|
+
|
60
|
+
# there's a few text callbacks, so make sure we process them all
|
61
|
+
alias :super_show_text :show_text
|
62
|
+
alias :move_to_next_line_and_show_text :show_text
|
63
|
+
alias :set_spacing_next_line_show_text :show_text
|
64
|
+
|
65
|
+
def show_text_with_positioning(*params)
|
66
|
+
params = params.first
|
67
|
+
params.each { |str| show_text(str) if str.kind_of?(String) }
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
data/specs/text_spec.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
4
|
+
|
5
|
+
context "The PDF::Wrapper class" do
|
6
|
+
specify "should be able to add ascii text to the canvas" do
|
7
|
+
msg = "Chunky Bacon"
|
8
|
+
pdf = PDF::Wrapper.new
|
9
|
+
pdf.text msg
|
10
|
+
|
11
|
+
receiver = PageTextReceiver.new
|
12
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
13
|
+
|
14
|
+
# TODO: test for the text is in the appropriate location on the page
|
15
|
+
receiver.content.first.should eql(msg)
|
16
|
+
end
|
17
|
+
|
18
|
+
specify "should be able to add unicode text to the canvas" do
|
19
|
+
msg = "メインページ"
|
20
|
+
pdf = PDF::Wrapper.new
|
21
|
+
pdf.text msg
|
22
|
+
|
23
|
+
receiver = PageTextReceiver.new
|
24
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
25
|
+
|
26
|
+
# TODO: test for the text is in the appropriate location on the page
|
27
|
+
receiver.content.first.should eql(msg)
|
28
|
+
end
|
29
|
+
|
30
|
+
specify "should be align text on the left when using the text method" do
|
31
|
+
msg = "Chunky Bacon"
|
32
|
+
pdf = PDF::Wrapper.new
|
33
|
+
pdf.text msg, :alignment => :left
|
34
|
+
|
35
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
36
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
37
|
+
|
38
|
+
# set_text_matrix_and_text_line_matrix - [10.666992, 0.0, 0.0, 10.666992, 265.0, 788.89]
|
39
|
+
|
40
|
+
# ensure the text is placed in the right location
|
41
|
+
params = receiver.first_occurance_of(:set_text_matrix_and_text_line_matrix)[:args]
|
42
|
+
params[4].should eql(pdf.margin_left.to_f)
|
43
|
+
end
|
44
|
+
|
45
|
+
specify "should be align text in the centre when using the text method" do
|
46
|
+
msg = "Chunky Bacon"
|
47
|
+
pdf = PDF::Wrapper.new
|
48
|
+
pdf.text msg, :alignment => :center
|
49
|
+
|
50
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
51
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
52
|
+
|
53
|
+
# ensure the text is placed in the right location - the left
|
54
|
+
# egde should be less than half way across the page, but not on the left margin
|
55
|
+
params = receiver.first_occurance_of(:set_text_matrix_and_text_line_matrix)[:args]
|
56
|
+
(params[4] < pdf.absolute_x_middle).should be_true
|
57
|
+
(params[4] > pdf.absolute_x_middle - 100).should be_true
|
58
|
+
end
|
59
|
+
|
60
|
+
specify "should be align text on the right when using the text method" do
|
61
|
+
msg = "Chunky Bacon"
|
62
|
+
pdf = PDF::Wrapper.new
|
63
|
+
pdf.text msg, :alignment => :right
|
64
|
+
|
65
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
66
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
67
|
+
|
68
|
+
# ensure the text is placed in the right location - the left
|
69
|
+
# egde should be more than half way across the page, but not on the right margin
|
70
|
+
params = receiver.first_occurance_of(:set_text_matrix_and_text_line_matrix)[:args]
|
71
|
+
(params[4] > pdf.absolute_x_middle).should be_true
|
72
|
+
(params[4] < pdf.absolute_right_margin).should be_true
|
73
|
+
end
|
74
|
+
|
75
|
+
specify "should be able to add text to the canvas in a bounding box using the cell method" do
|
76
|
+
msg = "メインページ"
|
77
|
+
pdf = PDF::Wrapper.new
|
78
|
+
pdf.cell msg, 100, 100, 200, 200
|
79
|
+
|
80
|
+
receiver = PageTextReceiver.new
|
81
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
82
|
+
|
83
|
+
# TODO: test for the text is in the appropriate location on the page
|
84
|
+
receiver.content.first.should eql(msg)
|
85
|
+
end
|
86
|
+
|
87
|
+
specify "should keep all text for a cell inside the cell boundaries" do
|
88
|
+
msg = "This is a text cell, added by James"
|
89
|
+
pdf = PDF::Wrapper.new
|
90
|
+
x = y = 100
|
91
|
+
w = h = 200
|
92
|
+
pdf.cell msg, x, y, w, h
|
93
|
+
|
94
|
+
receiver = PDF::Reader::RegisterReceiver.new
|
95
|
+
reader = PDF::Reader.string(pdf.render, receiver)
|
96
|
+
|
97
|
+
receiver.all(:set_text_matrix_and_text_line_matrix).each do |cb|
|
98
|
+
# horizontal location
|
99
|
+
# TODO: we're only testing the it doesn't start past the right boundary of the cell
|
100
|
+
# should also test that it doesn't start in the cell but overrun it
|
101
|
+
(cb[:args][4] >= x).should be_true
|
102
|
+
(cb[:args][4] <= x + w).should be_true
|
103
|
+
|
104
|
+
# vertical location
|
105
|
+
# TODO: we're only testing the it doesn't start past the bottom boundary of the cell
|
106
|
+
# should also test that it doesn't start in the cell but overrun it
|
107
|
+
cell_top_bound = pdf.page_height - y
|
108
|
+
(cb[:args][5] <= cell_top_bound).should be_true
|
109
|
+
(cb[:args][5] >= cell_top_bound - h).should be_true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
specify "should be able to calculate the height of a string of text" do
|
114
|
+
str = "This is a medium length string\nthat is also multi line. one two three four."
|
115
|
+
pdf = PDF::Wrapper.new
|
116
|
+
opts = {:font_size => 16, :font => "Sans Serif", :alignment => :left, :justify => false }
|
117
|
+
pdf.text_height(str, pdf.body_width, opts).should eql(49)
|
118
|
+
end
|
119
|
+
|
120
|
+
specify "should be able to calculate the width of a string of text" do
|
121
|
+
str = "James Healy"
|
122
|
+
str2 = "James Healy is a Ruby dev that lives in Melbourne, Australia. His day job mostly involved Ruby on Rails."
|
123
|
+
pdf = PDF::Wrapper.new
|
124
|
+
opts = {:font_size => 16, :font => "Sans Serif"}
|
125
|
+
pdf.text(str, opts)
|
126
|
+
pdf.text_width(str, opts).should eql(131)
|
127
|
+
pdf.text_width(str2, opts).should eql(1107)
|
128
|
+
end
|
129
|
+
|
130
|
+
specify "should raise an exception if build_pango_layout is passed anything other than a string" do
|
131
|
+
pdf = PDF::Wrapper.new
|
132
|
+
lambda { pdf.build_pango_layout(10) }.should raise_error(ArgumentError)
|
133
|
+
end
|
134
|
+
|
135
|
+
if RUBY_VERSION >= "1.9"
|
136
|
+
specify "should accept non UTF-8 strings to build_pango_layout and convert them on the fly" do
|
137
|
+
pdf = PDF::Wrapper.new
|
138
|
+
|
139
|
+
# all three of these files have the same content, but in different encodings
|
140
|
+
iso2022_str = File.open(File.dirname(__FILE__) + "/data/shift_jis.txt", "r:ISO-2022-JP") { |f| f.read }.strip!
|
141
|
+
shiftjis_str = File.open(File.dirname(__FILE__) + "/data/iso-2022-jp.txt", "r:Shift_JIS") { |f| f.read }.strip!
|
142
|
+
utf8_str = File.open(File.dirname(__FILE__) + "/data/utf8.txt", "r:UTF-8") { |f| f.read }.strip!
|
143
|
+
|
144
|
+
pdf.build_pango_layout(shiftjis_str)
|
145
|
+
pdf.build_pango_layout(iso2022_str)
|
146
|
+
|
147
|
+
# TODO: improve this spec using mocks. Atm, I'm assume that if build_pango_layout didn't raise an exception when
|
148
|
+
# passed in the non UTF-8 strings, then all worked fine. yuck.
|
149
|
+
end
|
150
|
+
|
151
|
+
specify "should raise an error when a string that isn't convertable to UTF-8 is passed into build_pango_layout()"
|
152
|
+
end
|
153
|
+
end
|
data/specs/wrapper_spec.rb
CHANGED
@@ -1,108 +1,9 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
require 'pdf/wrapper'
|
6
|
-
require 'tempfile'
|
7
|
-
require 'rubygems'
|
8
|
-
|
9
|
-
gem "pdf-reader", ">=0.6.1"
|
10
|
-
|
11
|
-
require 'pdf/reader'
|
12
|
-
|
13
|
-
# make some private methods of PDF::Wrapper public for testing
|
14
|
-
class PDF::Wrapper
|
15
|
-
public :build_pango_layout
|
16
|
-
public :calc_image_dimensions
|
17
|
-
public :load_librsvg
|
18
|
-
public :load_libpixbuf
|
19
|
-
public :load_libpango
|
20
|
-
public :load_libpoppler
|
21
|
-
public :default_text_options
|
22
|
-
public :detect_image_type
|
23
|
-
public :draw_pdf
|
24
|
-
public :draw_pixbuf
|
25
|
-
public :draw_png
|
26
|
-
public :draw_svg
|
27
|
-
public :validate_color
|
28
|
-
end
|
29
|
-
|
30
|
-
# a helper class for couting the number of pages in a PDF
|
31
|
-
class PageReceiver
|
32
|
-
attr_accessor :page_count
|
33
|
-
|
34
|
-
def initialize
|
35
|
-
@page_count = 0
|
36
|
-
end
|
37
|
-
|
38
|
-
# Called when page parsing ends
|
39
|
-
def end_page
|
40
|
-
@page_count += 1
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class PageTextReceiver
|
45
|
-
attr_accessor :content
|
46
|
-
|
47
|
-
def initialize
|
48
|
-
@content = []
|
49
|
-
end
|
50
|
-
|
51
|
-
# Called when page parsing starts
|
52
|
-
def begin_page(arg = nil)
|
53
|
-
@content << ""
|
54
|
-
end
|
55
|
-
|
56
|
-
def show_text(string, *params)
|
57
|
-
@content.last << string.strip
|
58
|
-
end
|
59
|
-
|
60
|
-
# there's a few text callbacks, so make sure we process them all
|
61
|
-
alias :super_show_text :show_text
|
62
|
-
alias :move_to_next_line_and_show_text :show_text
|
63
|
-
alias :set_spacing_next_line_show_text :show_text
|
64
|
-
|
65
|
-
def show_text_with_positioning(*params)
|
66
|
-
params = params.first
|
67
|
-
params.each { |str| show_text(str) if str.kind_of?(String) }
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
3
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
71
4
|
|
72
5
|
context "The PDF::Wrapper class" do
|
73
6
|
|
74
|
-
setup do
|
75
|
-
#@file = File.new(File.dirname(__FILE__) + "/data/cairo-basic.pdf")
|
76
|
-
@shortstr = "Chunky Bacon"
|
77
|
-
@medstr = "This is a medium length string\nthat is also multi line. one two three four."
|
78
|
-
end
|
79
|
-
|
80
|
-
specify "should load external libs correctly" do
|
81
|
-
pdf = PDF::Wrapper.new
|
82
|
-
|
83
|
-
# lib gdkpixbuf
|
84
|
-
::Object.const_defined?(:Gdk).should eql(false)
|
85
|
-
pdf.load_libpixbuf
|
86
|
-
::Object.const_defined?(:Gdk).should eql(true)
|
87
|
-
::Gdk.const_defined?(:Pixbuf).should eql(true)
|
88
|
-
|
89
|
-
# pango
|
90
|
-
::Object.const_defined?(:Pango).should eql(false)
|
91
|
-
pdf.load_libpango
|
92
|
-
::Object.const_defined?(:Pango).should eql(true)
|
93
|
-
|
94
|
-
# libpoppler
|
95
|
-
::Object.const_defined?(:Poppler).should eql(false)
|
96
|
-
pdf.load_libpoppler
|
97
|
-
::Object.const_defined?(:Poppler).should eql(true)
|
98
|
-
|
99
|
-
# librsvg
|
100
|
-
::Object.const_defined?(:RSVG).should eql(false)
|
101
|
-
pdf.load_librsvg
|
102
|
-
::Object.const_defined?(:RSVG).should eql(true)
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
7
|
specify "should initilize with the correct default paper size and orientation" do
|
107
8
|
pdf = PDF::Wrapper.new
|
108
9
|
pdf.page_width.should eql(PDF::Wrapper::PAGE_SIZES[:A4].first)
|
@@ -211,6 +112,16 @@ context "The PDF::Wrapper class" do
|
|
211
112
|
lambda {pdf.move_to(100, PDF::Wrapper::PAGE_SIZES[:A4].last + 10)}.should raise_error(ArgumentError)
|
212
113
|
end
|
213
114
|
|
115
|
+
specify "should be able to shift the y position of the cursor using pad" do
|
116
|
+
pdf = PDF::Wrapper.new
|
117
|
+
pdf.move_to(100,100)
|
118
|
+
newy = pdf.pad(25)
|
119
|
+
x,y = pdf.current_point
|
120
|
+
x.to_i.should eql(100)
|
121
|
+
y.to_i.should eql(125)
|
122
|
+
newy.should eql(125.0)
|
123
|
+
end
|
124
|
+
|
214
125
|
specify "should add additional pages at the users request" do
|
215
126
|
pdf = PDF::Wrapper.new
|
216
127
|
pdf.move_to(100,100)
|
@@ -225,79 +136,6 @@ context "The PDF::Wrapper class" do
|
|
225
136
|
receiver.page_count.should eql(2)
|
226
137
|
end
|
227
138
|
|
228
|
-
specify "should be able to draw a single line onto the canvas" do
|
229
|
-
x0 = y0 = 100
|
230
|
-
x1 = y1 = 200
|
231
|
-
pdf = PDF::Wrapper.new
|
232
|
-
pdf.line(x0,y0,x1,y1)
|
233
|
-
|
234
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
235
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
236
|
-
|
237
|
-
# the begin_new_subpath command specifies the start of the line, append line specifies the end
|
238
|
-
receiver.count(:begin_new_subpath).should eql(1)
|
239
|
-
receiver.count(:append_line).should eql(1)
|
240
|
-
receiver.first_occurance_of(:begin_new_subpath)[:args].should eql([x0.to_f, y0.to_f])
|
241
|
-
receiver.first_occurance_of(:append_line)[:args].should eql([x1.to_f, y1.to_f])
|
242
|
-
end
|
243
|
-
|
244
|
-
specify "should be able to draw a single line onto the canvas with a width of 5" do
|
245
|
-
x0 = y0 = 100
|
246
|
-
x1 = y1 = 200
|
247
|
-
width = 5
|
248
|
-
pdf = PDF::Wrapper.new
|
249
|
-
pdf.line(x0,y0,x1,y1, :line_width => width)
|
250
|
-
|
251
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
252
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
253
|
-
|
254
|
-
# the begin_new_subpath command specifies the start of the line, append line specifies the end
|
255
|
-
receiver.count(:set_line_width).should eql(1)
|
256
|
-
receiver.count(:begin_new_subpath).should eql(1)
|
257
|
-
receiver.count(:append_line).should eql(1)
|
258
|
-
receiver.first_occurance_of(:set_line_width)[:args].should eql([width.to_f])
|
259
|
-
receiver.first_occurance_of(:begin_new_subpath)[:args].should eql([x0.to_f, y0.to_f])
|
260
|
-
receiver.first_occurance_of(:append_line)[:args].should eql([x1.to_f, y1.to_f])
|
261
|
-
end
|
262
|
-
|
263
|
-
specify "should be able to draw an empty rectangle onto the canvas" do
|
264
|
-
x = y = 100
|
265
|
-
w = h = 200
|
266
|
-
pdf = PDF::Wrapper.new
|
267
|
-
pdf.rectangle(x,y,w,h)
|
268
|
-
|
269
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
270
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
271
|
-
|
272
|
-
# the begin_new_subpath command specifies the start of the line, append line specifies the end
|
273
|
-
callbacks = receiver.series(:begin_new_subpath, :append_line,:append_line,:append_line, :close_subpath)
|
274
|
-
callbacks.shift[:args].should eql([x.to_f, y.to_f])
|
275
|
-
callbacks.shift[:args].should eql([(x+w).to_f, y.to_f])
|
276
|
-
callbacks.shift[:args].should eql([(x+w).to_f, (y+h).to_f])
|
277
|
-
callbacks.shift[:args].should eql([x.to_f, (y+h).to_f])
|
278
|
-
end
|
279
|
-
|
280
|
-
specify "should be able to draw an empty rectangle onto the canvas with a line width of 5" do
|
281
|
-
x = y = 100
|
282
|
-
w = h = 200
|
283
|
-
width = 5
|
284
|
-
pdf = PDF::Wrapper.new
|
285
|
-
pdf.rectangle(x,y,w,h, :line_width => width)
|
286
|
-
|
287
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
288
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
289
|
-
|
290
|
-
# ensure the line width was set correctly
|
291
|
-
receiver.count(:set_line_width).should eql(1)
|
292
|
-
receiver.first_occurance_of(:set_line_width)[:args].should eql([width.to_f])
|
293
|
-
|
294
|
-
# the begin_new_subpath command specifies the start of the line, append line specifies the end
|
295
|
-
callbacks = receiver.series(:begin_new_subpath, :append_line,:append_line,:append_line, :close_subpath)
|
296
|
-
callbacks.shift[:args].should eql([x.to_f, y.to_f])
|
297
|
-
callbacks.shift[:args].should eql([(x+w).to_f, y.to_f])
|
298
|
-
callbacks.shift[:args].should eql([(x+w).to_f, (y+h).to_f])
|
299
|
-
callbacks.shift[:args].should eql([x.to_f, (y+h).to_f])
|
300
|
-
end
|
301
139
|
|
302
140
|
specify "should leave the cursor in the bottom left of a layout when new text is added" do
|
303
141
|
pdf = PDF::Wrapper.new
|
@@ -309,185 +147,10 @@ context "The PDF::Wrapper class" do
|
|
309
147
|
newx, newy = pdf.current_point
|
310
148
|
|
311
149
|
newx.should eql(x)
|
312
|
-
|
150
|
+
# the top of our text box, plus its height
|
313
151
|
newy.should eql(y + height)
|
314
152
|
end
|
315
153
|
|
316
|
-
specify "should be able to draw a filled rectangle onto the canvas"
|
317
|
-
=begin
|
318
|
-
do
|
319
|
-
x = y = 100
|
320
|
-
w = h = 200
|
321
|
-
pdf = PDF::Wrapper.new
|
322
|
-
pdf.rectangle(x,y,w,h, :fill_color => :red)
|
323
|
-
|
324
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
325
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
326
|
-
|
327
|
-
# TODO: test for the appropriate pattern of callbacks
|
328
|
-
end
|
329
|
-
=end
|
330
|
-
|
331
|
-
specify "should be able to draw an empty rounded rectangle onto the canvas"
|
332
|
-
=begin
|
333
|
-
do
|
334
|
-
x = y = 100
|
335
|
-
w = h = 200
|
336
|
-
r = 5
|
337
|
-
pdf = PDF::Wrapper.new
|
338
|
-
pdf.rounded_rectangle(x,y,w,h,r)
|
339
|
-
|
340
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
341
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
342
|
-
|
343
|
-
# TODO: test for the appropriate pattern of callbacks
|
344
|
-
end
|
345
|
-
=end
|
346
|
-
|
347
|
-
specify "should be able to draw an empty rounded rectangle onto the canvas with a line width of 5"
|
348
|
-
=begin
|
349
|
-
do
|
350
|
-
x = y = 100
|
351
|
-
w = h = 200
|
352
|
-
r = 5
|
353
|
-
w = 5
|
354
|
-
pdf = PDF::Wrapper.new
|
355
|
-
pdf.rounded_rectangle(x,y,w,h,r, :line_width => w)
|
356
|
-
|
357
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
358
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
359
|
-
|
360
|
-
# TODO: test for the appropriate pattern of callbacks
|
361
|
-
end
|
362
|
-
=end
|
363
|
-
|
364
|
-
specify "should be able to draw a filled rounded rectangle onto the canvas"
|
365
|
-
=begin
|
366
|
-
do
|
367
|
-
x = y = 100
|
368
|
-
w = h = 200
|
369
|
-
r = 5
|
370
|
-
pdf = PDF::Wrapper.new
|
371
|
-
pdf.rounded_rectangle(x,y,w,h,r, :fill_color => :red)
|
372
|
-
|
373
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
374
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
375
|
-
|
376
|
-
# TODO: test for the appropriate pattern of callbacks
|
377
|
-
end
|
378
|
-
=end
|
379
|
-
|
380
|
-
specify "should be able to draw an empty circle onto the canvas"
|
381
|
-
=begin
|
382
|
-
do
|
383
|
-
x = 100
|
384
|
-
y = 200
|
385
|
-
r = 5
|
386
|
-
pdf = PDF::Wrapper.new
|
387
|
-
pdf.circle(x,y,r)
|
388
|
-
|
389
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
390
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
391
|
-
|
392
|
-
# TODO: test for the appropriate pattern of callbacks
|
393
|
-
end
|
394
|
-
=end
|
395
|
-
|
396
|
-
specify "should be able to draw an empty circle onto the canvas with a line width of 5"
|
397
|
-
=begin
|
398
|
-
do
|
399
|
-
x = 100
|
400
|
-
y = 200
|
401
|
-
r = 5
|
402
|
-
w = 5
|
403
|
-
pdf = PDF::Wrapper.new
|
404
|
-
pdf.circle(x,y,r, :line_width => w)
|
405
|
-
|
406
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
407
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
408
|
-
|
409
|
-
# TODO: test for the appropriate pattern of callbacks
|
410
|
-
end
|
411
|
-
=end
|
412
|
-
|
413
|
-
specify "should be able to draw a filled circle onto the canvas"
|
414
|
-
=begin
|
415
|
-
do
|
416
|
-
x = 100
|
417
|
-
y = 200
|
418
|
-
r = 5
|
419
|
-
pdf = PDF::Wrapper.new
|
420
|
-
pdf.circle(x,y,r, :fill_color => :red)
|
421
|
-
|
422
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
423
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
424
|
-
|
425
|
-
# TODO: test for the appropriate pattern of callbacks
|
426
|
-
end
|
427
|
-
=end
|
428
|
-
|
429
|
-
specify "should be able to add ascii text to the canvas" do
|
430
|
-
msg = "Chunky Bacon"
|
431
|
-
pdf = PDF::Wrapper.new
|
432
|
-
pdf.text msg
|
433
|
-
|
434
|
-
receiver = PageTextReceiver.new
|
435
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
436
|
-
|
437
|
-
# TODO: test for the text is in the appropriate location on the page
|
438
|
-
receiver.content.first.should eql(msg)
|
439
|
-
end
|
440
|
-
|
441
|
-
specify "should be able to add unicode text to the canvas" do
|
442
|
-
msg = "メインページ"
|
443
|
-
pdf = PDF::Wrapper.new
|
444
|
-
pdf.text msg
|
445
|
-
|
446
|
-
receiver = PageTextReceiver.new
|
447
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
448
|
-
|
449
|
-
# TODO: test for the text is in the appropriate location on the page
|
450
|
-
receiver.content.first.should eql(msg)
|
451
|
-
end
|
452
|
-
|
453
|
-
specify "should be able to add text to the canvas in a bounding box using the cell method" do
|
454
|
-
msg = "メインページ"
|
455
|
-
pdf = PDF::Wrapper.new
|
456
|
-
pdf.cell msg, 100, 100, 200, 200
|
457
|
-
|
458
|
-
receiver = PageTextReceiver.new
|
459
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
460
|
-
|
461
|
-
# TODO: test for the text is in the appropriate location on the page
|
462
|
-
receiver.content.first.should eql(msg)
|
463
|
-
end
|
464
|
-
|
465
|
-
specify "should keep all text for a cell inside the cell boundaries" do
|
466
|
-
msg = "This is a text cell, added by James"
|
467
|
-
pdf = PDF::Wrapper.new
|
468
|
-
x = y = 100
|
469
|
-
w = h = 200
|
470
|
-
pdf.cell msg, x, y, w, h
|
471
|
-
|
472
|
-
receiver = PDF::Reader::RegisterReceiver.new
|
473
|
-
reader = PDF::Reader.string(pdf.render, receiver)
|
474
|
-
|
475
|
-
receiver.all(:set_text_matrix_and_text_line_matrix).each do |cb|
|
476
|
-
# horizontal location
|
477
|
-
# TODO: we're only testing the it doesn't start past the right boundary of the cell
|
478
|
-
# should also test that it doesn't start in the cell but overrun it
|
479
|
-
(cb[:args][4] >= x).should be_true
|
480
|
-
(cb[:args][4] <= x + w).should be_true
|
481
|
-
|
482
|
-
# vertical location
|
483
|
-
# TODO: we're only testing the it doesn't start past the bottom boundary of the cell
|
484
|
-
# should also test that it doesn't start in the cell but overrun it
|
485
|
-
cell_top_bound = pdf.page_height - y
|
486
|
-
(cb[:args][5] <= cell_top_bound).should be_true
|
487
|
-
(cb[:args][5] >= cell_top_bound - h).should be_true
|
488
|
-
end
|
489
|
-
end
|
490
|
-
|
491
154
|
specify "should be able to render to a file" do
|
492
155
|
# generate a PDF
|
493
156
|
msg = "Chunky Bacon"
|
@@ -508,21 +171,6 @@ context "The PDF::Wrapper class" do
|
|
508
171
|
tmp.unlink
|
509
172
|
end
|
510
173
|
|
511
|
-
specify "should be able to detect the filetype of an image" do
|
512
|
-
pdf = PDF::Wrapper.new
|
513
|
-
pdf.detect_image_type(File.dirname(__FILE__) + "/data/google.png").should eql(:png)
|
514
|
-
pdf.detect_image_type(File.dirname(__FILE__) + "/data/zits.gif").should eql(:gif)
|
515
|
-
pdf.detect_image_type(File.dirname(__FILE__) + "/data/orc.svg").should eql(:svg)
|
516
|
-
pdf.detect_image_type(File.dirname(__FILE__) + "/data/utf8-long.pdf").should eql(:pdf)
|
517
|
-
pdf.detect_image_type(File.dirname(__FILE__) + "/data/shipsail.jpg").should eql(:jpg)
|
518
|
-
end
|
519
|
-
|
520
|
-
specify "should be able to calculate the height of a string of text" do
|
521
|
-
pdf = PDF::Wrapper.new
|
522
|
-
opts = {:font_size => 16, :font => "Sans Serif", :alignment => :left, :justify => false }
|
523
|
-
pdf.text_height(@medstr, pdf.body_width, opts).should eql(49)
|
524
|
-
end
|
525
|
-
|
526
174
|
specify "should be able to draw a table on the canvas"
|
527
175
|
|
528
176
|
specify "should leave the cursor in the bottom left when adding a table" do
|
@@ -541,31 +189,6 @@ context "The PDF::Wrapper class" do
|
|
541
189
|
x.to_i.should eql(100)
|
542
190
|
end
|
543
191
|
|
544
|
-
specify "should raise an exception if build_pango_layout is passed anything other than a string" do
|
545
|
-
pdf = PDF::Wrapper.new
|
546
|
-
lambda { pdf.build_pango_layout(10) }.should raise_error(ArgumentError)
|
547
|
-
|
548
|
-
end
|
549
|
-
|
550
|
-
if RUBY_VERSION >= "1.9"
|
551
|
-
specify "should accept non UTF-8 strings to build_pango_layout and convert them on the fly" do
|
552
|
-
pdf = PDF::Wrapper.new
|
553
|
-
|
554
|
-
# all three of these files have the same content, but in different encodings
|
555
|
-
iso2022_str = File.open(File.dirname(__FILE__) + "/data/shift_jis.txt", "r:ISO-2022-JP") { |f| f.read }.strip!
|
556
|
-
shiftjis_str = File.open(File.dirname(__FILE__) + "/data/iso-2022-jp.txt", "r:Shift_JIS") { |f| f.read }.strip!
|
557
|
-
utf8_str = File.open(File.dirname(__FILE__) + "/data/utf8.txt", "r:UTF-8") { |f| f.read }.strip!
|
558
|
-
|
559
|
-
pdf.build_pango_layout(shiftjis_str)
|
560
|
-
pdf.build_pango_layout(iso2022_str)
|
561
|
-
|
562
|
-
# TODO: improve this spec using mocks. Atm, I'm assume that if build_pango_layout didn't raise an exception when
|
563
|
-
# passed in the non UTF-8 strings, then all worked fine. yuck.
|
564
|
-
end
|
565
|
-
|
566
|
-
specify "should raise an error when a string that isn't convertable to UTF-8 is passed into build_pango_layout()"
|
567
|
-
end
|
568
|
-
|
569
192
|
specify "should be able to determine if a requested colour is valid or not" do
|
570
193
|
pdf = PDF::Wrapper.new
|
571
194
|
pdf.validate_color(:black).should be_true
|
@@ -794,12 +417,4 @@ context "The PDF::Wrapper class" do
|
|
794
417
|
lambda { pdf.rounded_rectangle(100,100,100,100,10, :ponies => true)}.should raise_error(ArgumentError)
|
795
418
|
lambda { pdf.image(File.dirname(__FILE__) + "/data/orc.svg", :ponies => true)}.should raise_error(ArgumentError)
|
796
419
|
end
|
797
|
-
|
798
|
-
specify "should be able to calculate image dimensions correctly" do
|
799
|
-
pdf = PDF::Wrapper.new
|
800
|
-
pdf.calc_image_dimensions(100, 100, 200, 200).should eql([100.0,100.0])
|
801
|
-
pdf.calc_image_dimensions(nil, nil, 200, 200).should eql([200.0,200.0])
|
802
|
-
pdf.calc_image_dimensions(150, 200, 200, 200, true).should eql([150.0,150.0])
|
803
|
-
pdf.calc_image_dimensions(300, 250, 200, 200, true).should eql([250.0,250.0])
|
804
|
-
end
|
805
420
|
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.5
|
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-
|
12
|
+
date: 2008-04-27 00:00:00 +10:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -24,28 +24,33 @@ extra_rdoc_files:
|
|
24
24
|
- CHANGELOG
|
25
25
|
- TODO
|
26
26
|
files:
|
27
|
-
- examples/repeating.rb
|
28
27
|
- examples/cell.rb
|
29
28
|
- examples/image.rb
|
30
|
-
- examples/
|
31
|
-
- examples/table.rb
|
29
|
+
- examples/repeating.rb
|
32
30
|
- examples/shapes.rb
|
31
|
+
- examples/table.rb
|
32
|
+
- examples/utf8-long.rb
|
33
33
|
- examples/utf8.rb
|
34
34
|
- lib/pdf
|
35
|
-
- lib/pdf/wrapper.rb
|
36
35
|
- lib/pdf/core.rb
|
36
|
+
- lib/pdf/wrapper.rb
|
37
37
|
- specs/data
|
38
|
-
- specs/data/shift_jis.txt
|
39
38
|
- specs/data/google.png
|
40
|
-
- specs/data/utf8-long.txt
|
41
39
|
- specs/data/iso-2022-jp.txt
|
42
|
-
- specs/data/utf8.txt
|
43
|
-
- specs/data/shipsail.jpg
|
44
|
-
- specs/data/zits.gif
|
45
40
|
- specs/data/orc.svg
|
41
|
+
- specs/data/shift_jis.txt
|
42
|
+
- specs/data/shipsail.jpg
|
46
43
|
- specs/data/stef.jpg
|
47
44
|
- specs/data/utf8-long.pdf
|
45
|
+
- specs/data/utf8-long.txt
|
46
|
+
- specs/data/utf8.txt
|
47
|
+
- specs/data/zits.gif
|
48
48
|
- specs/wrapper_spec.rb
|
49
|
+
- specs/load_spec.rb
|
50
|
+
- specs/shapes_spec.rb
|
51
|
+
- specs/text_spec.rb
|
52
|
+
- specs/spec_helper.rb
|
53
|
+
- specs/image_spec.rb
|
49
54
|
- Rakefile
|
50
55
|
- README
|
51
56
|
- CHANGELOG
|