prawn 1.0.0.rc1 → 1.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +18 -0
- data/README.md +5 -3
- data/Rakefile +8 -14
- data/data/pdfs/nested_pages.pdf +13 -13
- data/lib/prawn.rb +3 -1
- data/lib/prawn/compatibility.rb +46 -10
- data/lib/prawn/core.rb +3 -1
- data/lib/prawn/core/document_state.rb +2 -1
- data/lib/prawn/core/object_store.rb +61 -5
- data/lib/prawn/core/page.rb +3 -6
- data/lib/prawn/core/pdf_object.rb +21 -4
- data/lib/prawn/core/reference.rb +6 -2
- data/lib/prawn/core/text.rb +4 -4
- data/lib/prawn/core/text/formatted/line_wrap.rb +23 -8
- data/lib/prawn/document.rb +21 -15
- data/lib/prawn/document/bounding_box.rb +3 -3
- data/lib/prawn/document/column_box.rb +22 -4
- data/lib/prawn/document/snapshot.rb +1 -1
- data/lib/prawn/encoding.rb +1 -1
- data/lib/prawn/errors.rb +4 -0
- data/lib/prawn/font.rb +1 -1
- data/lib/prawn/font/afm.rb +30 -72
- data/lib/prawn/font/ttf.rb +6 -33
- data/lib/prawn/graphics.rb +148 -23
- data/lib/prawn/graphics/color.rb +8 -1
- data/lib/prawn/graphics/patterns.rb +137 -0
- data/lib/prawn/images.rb +25 -19
- data/lib/prawn/images/jpg.rb +4 -4
- data/lib/prawn/images/png.rb +18 -12
- data/lib/prawn/security.rb +6 -4
- data/lib/prawn/soft_mask.rb +94 -0
- data/lib/prawn/table.rb +136 -31
- data/lib/prawn/table/cell.rb +260 -29
- data/lib/prawn/table/cell/span_dummy.rb +88 -0
- data/lib/prawn/table/cell/text.rb +36 -14
- data/lib/prawn/table/cells.rb +91 -41
- data/lib/prawn/text.rb +3 -2
- data/lib/prawn/text/formatted/box.rb +14 -5
- data/lib/prawn/text/formatted/fragment.rb +33 -22
- data/lib/prawn/text/formatted/parser.rb +5 -2
- data/lib/prawn/utilities.rb +44 -0
- data/manual/basic_concepts/adding_pages.rb +27 -0
- data/manual/basic_concepts/basic_concepts.rb +34 -0
- data/manual/basic_concepts/creation.rb +39 -0
- data/manual/basic_concepts/cursor.rb +33 -0
- data/manual/basic_concepts/measurement.rb +25 -0
- data/manual/basic_concepts/origin.rb +38 -0
- data/manual/basic_concepts/other_cursor_helpers.rb +40 -0
- data/manual/bounding_box/bounding_box.rb +39 -0
- data/manual/bounding_box/bounds.rb +49 -0
- data/manual/bounding_box/canvas.rb +24 -0
- data/manual/bounding_box/creation.rb +23 -0
- data/manual/bounding_box/indentation.rb +46 -0
- data/manual/bounding_box/nesting.rb +45 -0
- data/manual/bounding_box/russian_boxes.rb +40 -0
- data/manual/bounding_box/stretchy.rb +31 -0
- data/manual/document_and_page_options/background.rb +27 -0
- data/manual/document_and_page_options/document_and_page_options.rb +31 -0
- data/manual/document_and_page_options/metadata.rb +23 -0
- data/manual/document_and_page_options/page_margins.rb +38 -0
- data/manual/document_and_page_options/page_size.rb +34 -0
- data/manual/example_file.rb +116 -0
- data/manual/example_helper.rb +430 -0
- data/manual/example_package.rb +53 -0
- data/manual/example_section.rb +46 -0
- data/manual/graphics/circle_and_ellipse.rb +22 -0
- data/manual/graphics/color.rb +24 -0
- data/manual/graphics/common_lines.rb +28 -0
- data/manual/graphics/fill_and_stroke.rb +42 -0
- data/manual/graphics/fill_rules.rb +37 -0
- data/manual/graphics/gradients.rb +37 -0
- data/manual/graphics/graphics.rb +58 -0
- data/manual/graphics/helper.rb +17 -0
- data/manual/graphics/line_width.rb +35 -0
- data/manual/graphics/lines_and_curves.rb +41 -0
- data/manual/graphics/polygon.rb +29 -0
- data/manual/graphics/rectangle.rb +21 -0
- data/manual/graphics/rotate.rb +28 -0
- data/manual/graphics/scale.rb +41 -0
- data/manual/graphics/soft_masks.rb +46 -0
- data/manual/graphics/stroke_cap.rb +31 -0
- data/manual/graphics/stroke_dash.rb +43 -0
- data/manual/graphics/stroke_join.rb +30 -0
- data/manual/graphics/translate.rb +29 -0
- data/manual/graphics/transparency.rb +35 -0
- data/manual/images/absolute_position.rb +23 -0
- data/manual/images/fit.rb +21 -0
- data/manual/images/horizontal.rb +25 -0
- data/manual/images/images.rb +40 -0
- data/manual/images/plain_image.rb +18 -0
- data/manual/images/scale.rb +22 -0
- data/manual/images/vertical.rb +28 -0
- data/manual/images/width_and_height.rb +25 -0
- data/manual/layout/boxes.rb +27 -0
- data/manual/layout/content.rb +25 -0
- data/manual/layout/layout.rb +28 -0
- data/manual/layout/simple_grid.rb +23 -0
- data/manual/manual/cover.rb +26 -0
- data/manual/manual/foreword.rb +13 -0
- data/manual/manual/how_to_read_this_manual.rb +41 -0
- data/manual/manual/manual.rb +36 -0
- data/manual/outline/add_subsection_to.rb +61 -0
- data/manual/outline/insert_section_after.rb +47 -0
- data/manual/outline/outline.rb +32 -0
- data/manual/outline/sections_and_pages.rb +67 -0
- data/manual/repeatable_content/page_numbering.rb +54 -0
- data/manual/repeatable_content/repeatable_content.rb +31 -0
- data/manual/repeatable_content/repeater.rb +55 -0
- data/manual/repeatable_content/stamp.rb +41 -0
- data/manual/security/encryption.rb +31 -0
- data/manual/security/permissions.rb +38 -0
- data/manual/security/security.rb +28 -0
- data/manual/syntax_highlight.rb +52 -0
- data/manual/table/basic_block.rb +53 -0
- data/manual/table/before_rendering_page.rb +26 -0
- data/manual/table/cell_border_lines.rb +24 -0
- data/manual/table/cell_borders_and_bg.rb +31 -0
- data/manual/table/cell_dimensions.rb +30 -0
- data/manual/table/cell_text.rb +38 -0
- data/manual/table/column_widths.rb +30 -0
- data/manual/table/content_and_subtables.rb +39 -0
- data/manual/table/creation.rb +27 -0
- data/manual/table/filtering.rb +36 -0
- data/manual/table/flow_and_header.rb +17 -0
- data/manual/table/image_cells.rb +33 -0
- data/manual/table/position.rb +29 -0
- data/manual/table/row_colors.rb +20 -0
- data/manual/table/span.rb +30 -0
- data/manual/table/style.rb +22 -0
- data/manual/table/table.rb +52 -0
- data/manual/table/width.rb +27 -0
- data/manual/templates/full_template.rb +23 -0
- data/manual/templates/page_template.rb +47 -0
- data/manual/templates/templates.rb +26 -0
- data/manual/text/alignment.rb +44 -0
- data/manual/text/color.rb +24 -0
- data/manual/text/column_box.rb +32 -0
- data/manual/text/fallback_fonts.rb +37 -0
- data/manual/text/font.rb +41 -0
- data/manual/text/font_size.rb +45 -0
- data/manual/text/font_style.rb +23 -0
- data/manual/text/formatted_callbacks.rb +60 -0
- data/manual/text/formatted_text.rb +50 -0
- data/manual/text/free_flowing_text.rb +51 -0
- data/manual/text/group.rb +29 -0
- data/manual/text/inline.rb +43 -0
- data/manual/text/kerning_and_character_spacing.rb +39 -0
- data/manual/text/leading.rb +25 -0
- data/manual/text/line_wrapping.rb +41 -0
- data/manual/text/paragraph_indentation.rb +26 -0
- data/manual/text/positioned_text.rb +38 -0
- data/manual/text/registering_families.rb +48 -0
- data/manual/text/rendering_and_color.rb +37 -0
- data/manual/text/right_to_left_text.rb +43 -0
- data/manual/text/rotation.rb +43 -0
- data/manual/text/single_usage.rb +37 -0
- data/manual/text/text.rb +75 -0
- data/manual/text/text_box_excess.rb +32 -0
- data/manual/text/text_box_extensions.rb +45 -0
- data/manual/text/text_box_overflow.rb +44 -0
- data/manual/text/utf8.rb +28 -0
- data/manual/text/win_ansi_charset.rb +59 -0
- data/prawn.gemspec +10 -7
- data/spec/bounding_box_spec.rb +107 -17
- data/spec/cell_spec.rb +66 -40
- data/spec/column_box_spec.rb +33 -0
- data/spec/document_spec.rb +45 -24
- data/spec/extensions/encoding_helpers.rb +6 -0
- data/spec/extensions/mocha.rb +1 -0
- data/spec/font_spec.rb +71 -53
- data/spec/formatted_text_arranger_spec.rb +19 -19
- data/spec/formatted_text_box_spec.rb +16 -16
- data/spec/formatted_text_fragment_spec.rb +6 -6
- data/spec/graphics_spec.rb +96 -31
- data/spec/grid_spec.rb +2 -2
- data/spec/images_spec.rb +18 -10
- data/spec/jpg_spec.rb +1 -1
- data/spec/line_wrap_spec.rb +14 -14
- data/spec/measurement_units_spec.rb +2 -2
- data/spec/name_tree_spec.rb +6 -6
- data/spec/object_store_spec.rb +17 -17
- data/spec/outline_spec.rb +35 -17
- data/spec/pdf_object_spec.rb +3 -1
- data/spec/png_spec.rb +22 -19
- data/spec/reference_spec.rb +24 -1
- data/spec/repeater_spec.rb +9 -9
- data/spec/security_spec.rb +3 -3
- data/spec/snapshot_spec.rb +3 -3
- data/spec/soft_mask_spec.rb +117 -0
- data/spec/span_spec.rb +4 -4
- data/spec/spec_helper.rb +12 -6
- data/spec/stamp_spec.rb +12 -12
- data/spec/stroke_styles_spec.rb +5 -5
- data/spec/table_spec.rb +458 -88
- data/spec/template_spec.rb +108 -54
- data/spec/text_at_spec.rb +17 -17
- data/spec/text_box_spec.rb +76 -45
- data/spec/text_rendering_mode_spec.rb +5 -5
- data/spec/text_spacing_spec.rb +4 -4
- data/spec/text_spec.rb +44 -40
- metadata +419 -250
- data/lib/prawn/graphics/gradient.rb +0 -84
- data/lib/prawn/security/arcfour.rb +0 -51
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source :rubygems
|
2
|
+
|
3
|
+
gem "ttfunk", "~>1.0.3"
|
4
|
+
gem "pdf-reader", "~> 1.2"
|
5
|
+
gem "ruby-rc4"
|
6
|
+
gem "afm"
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
gem "coderay", "~> 1.0.7"
|
10
|
+
gem "rdoc"
|
11
|
+
end
|
12
|
+
|
13
|
+
group :test do
|
14
|
+
gem "pdf-inspector", "~> 1.0.2", :require => "pdf/inspector"
|
15
|
+
gem "rspec"
|
16
|
+
gem "mocha", :require => false
|
17
|
+
gem "rake"
|
18
|
+
end
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Prawn: Fast, Nimble PDF Generation For Ruby
|
2
2
|
|
3
|
+
[![Build Status](https://secure.travis-ci.org/prawnpdf/prawn.png)](http://travis-ci.org/prawnpdf/prawn)
|
4
|
+
|
3
5
|
Prawn is a pure Ruby PDF generation library that provides a lot of great functionality while trying to remain simple and reasonably performant. Here are some of the important features we provide:
|
4
6
|
|
5
7
|
* Vector drawing support, including lines, polygons, curves, ellipses, etc.
|
@@ -33,7 +35,7 @@ You can also install from git if you'd like, the _master_ branch contains the la
|
|
33
35
|
|
34
36
|
## Release Policies
|
35
37
|
|
36
|
-
We may introduce backwards incompatible changes each time our minor version number is bumped, but that any tiny version number bump should be bug fixes and internal changes only. Be sure to read the release notes each time we cut a new release and lock your gems accordingly. You can find the project CHANGELOG at: https://github.com/
|
38
|
+
We may introduce backwards incompatible changes each time our minor version number is bumped, but that any tiny version number bump should be bug fixes and internal changes only. Be sure to read the release notes each time we cut a new release and lock your gems accordingly. You can find the project CHANGELOG at: https://github.com/prawnpdf/prawn/wiki/CHANGELOG
|
37
39
|
|
38
40
|
## Hello World!
|
39
41
|
|
@@ -73,7 +75,7 @@ Please make your posts to the list as specific as possible, including code sampl
|
|
73
75
|
|
74
76
|
If you've found a bug, want to submit a patch, or have a feature request, please enter a ticket into our github tracker:
|
75
77
|
|
76
|
-
<http://github.com/
|
78
|
+
<http://github.com/prawnpdf/prawn/issues>
|
77
79
|
|
78
80
|
We strongly encourage bug reports to come with failing tests or at least a reduced example that demonstrates the problem. Similarly, patches should include tests, API documentation, and an update to the manual where relevant. Feel free to send a pull request early though, if you just want some feedback or a code review before preparing your code to be merged.
|
79
81
|
|
@@ -87,7 +89,7 @@ Over the last several years, we've received code contributions from over 50 peop
|
|
87
89
|
|
88
90
|
While he was only with us for a short time before moving on to other things, we'd also like to thank Prawn core team emeritus Jamis Buck for his contributions. He was responsible for introducing font subsetting as well as the first implementation of our inline formatting support.
|
89
91
|
|
90
|
-
You can find the full list of folks who have at least one patch accepted to Prawn on github at https://github.com/
|
92
|
+
You can find the full list of folks who have at least one patch accepted to Prawn on github at https://github.com/prawnpdf/prawn/contributors
|
91
93
|
|
92
94
|
## License
|
93
95
|
|
data/Rakefile
CHANGED
@@ -1,21 +1,15 @@
|
|
1
|
-
require "rubygems"
|
2
1
|
require "bundler"
|
3
2
|
Bundler.setup
|
4
3
|
|
5
4
|
require 'rake'
|
6
|
-
require '
|
7
|
-
require
|
8
|
-
require
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
require 'rdoc/task'
|
7
|
+
require 'rubygems/package_task'
|
9
8
|
|
10
|
-
task :default => [:
|
9
|
+
task :default => [:spec]
|
11
10
|
|
12
|
-
desc "Run all
|
13
|
-
|
14
|
-
# test.ruby_opts << "-w" # .should == true triggers a lot of warnings
|
15
|
-
test.libs << "spec"
|
16
|
-
test.test_files = Dir[ "spec/*_spec.rb" ]
|
17
|
-
test.verbose = true
|
18
|
-
end
|
11
|
+
desc "Run all rspec files"
|
12
|
+
RSpec::Core::RakeTask.new("spec")
|
19
13
|
|
20
14
|
desc "Show library's code statistics"
|
21
15
|
task :stats do
|
@@ -26,7 +20,7 @@ task :stats do
|
|
26
20
|
end
|
27
21
|
|
28
22
|
desc "genrates documentation"
|
29
|
-
|
23
|
+
RDoc::Task.new do |rdoc|
|
30
24
|
rdoc.rdoc_files.include( "README",
|
31
25
|
"COPYING",
|
32
26
|
"LICENSE",
|
@@ -45,7 +39,7 @@ task :manual do
|
|
45
39
|
end
|
46
40
|
|
47
41
|
spec = Gem::Specification.load "prawn.gemspec"
|
48
|
-
|
42
|
+
Gem::PackageTask.new(spec) do |pkg|
|
49
43
|
pkg.need_zip = true
|
50
44
|
pkg.need_tar = true
|
51
45
|
end
|
data/data/pdfs/nested_pages.pdf
CHANGED
@@ -49,7 +49,7 @@ endobj
|
|
49
49
|
>>
|
50
50
|
/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
|
51
51
|
>>
|
52
|
-
/Parent
|
52
|
+
/Parent 3 0 R
|
53
53
|
>>
|
54
54
|
endobj
|
55
55
|
7 0 obj
|
@@ -85,7 +85,7 @@ endobj
|
|
85
85
|
>>
|
86
86
|
/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
|
87
87
|
>>
|
88
|
-
/Parent
|
88
|
+
/Parent 3 0 R
|
89
89
|
>>
|
90
90
|
endobj
|
91
91
|
10 0 obj
|
@@ -97,17 +97,17 @@ endobj
|
|
97
97
|
endobj
|
98
98
|
xref
|
99
99
|
0 11
|
100
|
-
0000000000 65535 f
|
101
|
-
0000000015 00000 n
|
102
|
-
0000000071 00000 n
|
103
|
-
0000000120 00000 n
|
104
|
-
0000000183 00000 n
|
105
|
-
0000000240 00000 n
|
106
|
-
0000000494 00000 n
|
107
|
-
0000000672 00000 n
|
108
|
-
0000000769 00000 n
|
109
|
-
0000000994 00000 n
|
110
|
-
0000001173 00000 n
|
100
|
+
0000000000 65535 f
|
101
|
+
0000000015 00000 n
|
102
|
+
0000000071 00000 n
|
103
|
+
0000000120 00000 n
|
104
|
+
0000000183 00000 n
|
105
|
+
0000000240 00000 n
|
106
|
+
0000000494 00000 n
|
107
|
+
0000000672 00000 n
|
108
|
+
0000000769 00000 n
|
109
|
+
0000000994 00000 n
|
110
|
+
0000001173 00000 n
|
111
111
|
trailer
|
112
112
|
<< /Root 2 0 R
|
113
113
|
/Size 11
|
data/lib/prawn.rb
CHANGED
@@ -5,9 +5,10 @@
|
|
5
5
|
# into the lib/prawn/core/* source tree.
|
6
6
|
#
|
7
7
|
module Prawn #:nodoc:
|
8
|
-
VERSION = "1.0.0.
|
8
|
+
VERSION = "1.0.0.rc2"
|
9
9
|
end
|
10
10
|
|
11
|
+
require "prawn/utilities"
|
11
12
|
require "prawn/core"
|
12
13
|
require "prawn/text"
|
13
14
|
require "prawn/graphics"
|
@@ -16,6 +17,7 @@ require "prawn/images/image"
|
|
16
17
|
require "prawn/images/jpg"
|
17
18
|
require "prawn/images/png"
|
18
19
|
require "prawn/stamp"
|
20
|
+
require "prawn/soft_mask"
|
19
21
|
require "prawn/security"
|
20
22
|
require "prawn/document"
|
21
23
|
require "prawn/font"
|
data/lib/prawn/compatibility.rb
CHANGED
@@ -1,24 +1,60 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
3
|
+
# Compatibility layer to smooth over differences between Ruby implementations
|
4
|
+
# The oldest version of Ruby which is supported is MRI 1.8.7
|
5
|
+
# Ideally, all version-specific or implementation-specific code should be
|
6
|
+
# kept in this file (but that ideal has not been attained yet)
|
7
|
+
|
6
8
|
class String #:nodoc:
|
7
9
|
def first_line
|
8
10
|
self.each_line { |line| return line }
|
9
11
|
end
|
10
|
-
|
11
|
-
|
12
|
+
|
13
|
+
unless "".respond_to?(:codepoints)
|
14
|
+
def codepoints(&block)
|
15
|
+
if block_given?
|
16
|
+
unpack("U*").each(&block)
|
17
|
+
else
|
18
|
+
unpack("U*")
|
19
|
+
end
|
20
|
+
end
|
12
21
|
end
|
13
|
-
|
14
|
-
|
15
|
-
|
22
|
+
|
23
|
+
if "".respond_to?(:encode)
|
24
|
+
def normalize_to_utf8
|
25
|
+
begin
|
26
|
+
encode(Encoding::UTF_8)
|
27
|
+
rescue
|
28
|
+
raise Prawn::Errors::IncompatibleStringEncoding, "Encoding " +
|
29
|
+
"#{text.encoding} can not be transparently converted to UTF-8. " +
|
30
|
+
"Please ensure the encoding of the string you are attempting " +
|
31
|
+
"to use is set correctly"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
alias :unicode_characters :each_char
|
35
|
+
alias :unicode_length :length
|
36
|
+
|
37
|
+
else
|
38
|
+
def normalize_to_utf8
|
39
|
+
begin
|
40
|
+
# use unpack as a hackish way to verify the string is valid utf-8
|
41
|
+
unpack("U*")
|
42
|
+
return dup
|
43
|
+
rescue
|
44
|
+
raise Prawn::Errors::IncompatibleStringEncoding, "The string you " +
|
45
|
+
"are attempting to render is not encoded in valid UTF-8."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
def unicode_characters
|
16
49
|
if block_given?
|
17
|
-
|
50
|
+
unpack("U*").each { |c| yield [c].pack("U") }
|
18
51
|
else
|
19
|
-
|
52
|
+
unpack("U*").map { |c| [c].pack("U") }
|
20
53
|
end
|
21
54
|
end
|
55
|
+
def unicode_length
|
56
|
+
unpack("U*").length
|
57
|
+
end
|
22
58
|
end
|
23
59
|
end
|
24
60
|
|
data/lib/prawn/core.rb
CHANGED
@@ -29,7 +29,9 @@ module Prawn
|
|
29
29
|
|
30
30
|
# The base source directory for Prawn as installed on the system
|
31
31
|
#
|
32
|
-
|
32
|
+
#
|
33
|
+
BASEDIR = File.expand_path(File.join(dir, '..','..'))
|
34
|
+
DATADIR = File.expand_path(File.join(dir, '..', '..', 'data'))
|
33
35
|
|
34
36
|
# Whe set to true, Prawn will verify hash options to ensure only valid keys
|
35
37
|
# are used. Off by default.
|
@@ -6,6 +6,7 @@ module Prawn
|
|
6
6
|
|
7
7
|
if options[:template]
|
8
8
|
@store = Prawn::Core::ObjectStore.new(:template => options[:template])
|
9
|
+
@store.info.data.merge!(options[:info]) if options[:info]
|
9
10
|
else
|
10
11
|
@store = Prawn::Core::ObjectStore.new(:info => options[:info])
|
11
12
|
end
|
@@ -41,7 +42,7 @@ module Prawn
|
|
41
42
|
def normalize_metadata(options)
|
42
43
|
options[:info] ||= {}
|
43
44
|
options[:info][:Creator] ||= "Prawn"
|
44
|
-
options[:info][:Producer]
|
45
|
+
options[:info][:Producer] ||= "Prawn"
|
45
46
|
|
46
47
|
info = options[:info]
|
47
48
|
end
|
@@ -141,16 +141,32 @@ module Prawn
|
|
141
141
|
# Imports nothing and returns nil if the requested page number doesn't
|
142
142
|
# exist. page_num is 1 indexed, so 1 indicates the first page.
|
143
143
|
#
|
144
|
-
def import_page(
|
144
|
+
def import_page(input, page_num)
|
145
145
|
@loaded_objects = {}
|
146
|
-
|
147
|
-
|
146
|
+
if template_id = indexed_template(input, page_num)
|
147
|
+
return template_id
|
148
148
|
end
|
149
149
|
|
150
|
-
|
150
|
+
io = if input.respond_to?(:seek) && input.respond_to?(:read)
|
151
|
+
input
|
152
|
+
elsif File.file?(input.to_s)
|
153
|
+
StringIO.new(File.binread(input.to_s))
|
154
|
+
else
|
155
|
+
raise ArgumentError, "input must be an IO-like object or a filename"
|
156
|
+
end
|
157
|
+
|
158
|
+
# unless File.file?(filename)
|
159
|
+
# raise ArgumentError, "#{filename} does not exist"
|
160
|
+
# end
|
161
|
+
|
162
|
+
hash = indexed_hash(input, io)
|
151
163
|
ref = hash.page_references[page_num - 1]
|
152
164
|
|
153
|
-
ref.nil?
|
165
|
+
if ref.nil?
|
166
|
+
nil
|
167
|
+
else
|
168
|
+
index_template(input, page_num, load_object_graph(hash, ref).identifier)
|
169
|
+
end
|
154
170
|
|
155
171
|
rescue PDF::Reader::MalformedPDFError, PDF::Reader::InvalidObjectError
|
156
172
|
msg = "Error reading template file. If you are sure it's a valid PDF, it may be a bug."
|
@@ -162,6 +178,46 @@ module Prawn
|
|
162
178
|
|
163
179
|
private
|
164
180
|
|
181
|
+
# An index for page templates so that their loaded object graph
|
182
|
+
# can be reused without multiple loading
|
183
|
+
def template_index
|
184
|
+
@template_index ||= {}
|
185
|
+
end
|
186
|
+
|
187
|
+
# An index for the read object hash of a pdf template so that the
|
188
|
+
# object hash does not need to be parsed multiple times when using
|
189
|
+
# different pages of the pdf as page templates
|
190
|
+
def hash_index
|
191
|
+
@hash_index ||= {}
|
192
|
+
end
|
193
|
+
|
194
|
+
# returns the indexed object graph identifier for a template page if
|
195
|
+
# it exists
|
196
|
+
def indexed_template(input, page_number)
|
197
|
+
key = indexing_key(input)
|
198
|
+
template_index[key] && template_index[key][page_number]
|
199
|
+
end
|
200
|
+
|
201
|
+
# indexes the identifier for a page from a template
|
202
|
+
def index_template(input, page_number, id)
|
203
|
+
(template_index[indexing_key(input)] ||= {})[page_number] ||= id
|
204
|
+
end
|
205
|
+
|
206
|
+
# reads and indexes a new IO for a template
|
207
|
+
# if the IO has been indexed already then the parsed object hash
|
208
|
+
# is returned directly
|
209
|
+
def indexed_hash(input, io)
|
210
|
+
hash_index[indexing_key(input)] ||= PDF::Reader::ObjectHash.new(io)
|
211
|
+
end
|
212
|
+
|
213
|
+
# the index key for the input.
|
214
|
+
# uses object_id so that both a string filename or an IO stream can be
|
215
|
+
# indexed and reused provided the same object gets used in multiple page
|
216
|
+
# template calls.
|
217
|
+
def indexing_key(input)
|
218
|
+
input.object_id
|
219
|
+
end
|
220
|
+
|
165
221
|
# returns a nested array of object IDs for all pages in this object store.
|
166
222
|
#
|
167
223
|
def get_page_objects(obj)
|
data/lib/prawn/core/page.rb
CHANGED
@@ -63,7 +63,6 @@ module Prawn
|
|
63
63
|
document.restore_graphics_state
|
64
64
|
end
|
65
65
|
|
66
|
-
@stamp_dictionary.data[:Length] = @stamp_stream.length + 1
|
67
66
|
@stamp_dictionary << @stamp_stream
|
68
67
|
|
69
68
|
@stamp_stream = nil
|
@@ -84,7 +83,7 @@ module Prawn
|
|
84
83
|
unless dictionary.data[:Contents].is_a?(Array)
|
85
84
|
dictionary.data[:Contents] = [content]
|
86
85
|
end
|
87
|
-
@content = document.ref(
|
86
|
+
@content = document.ref({})
|
88
87
|
dictionary.data[:Contents] << document.state.store[@content]
|
89
88
|
document.open_graphics_state
|
90
89
|
end
|
@@ -129,11 +128,9 @@ module Prawn
|
|
129
128
|
if dictionary.data[:Contents].is_a?(Array)
|
130
129
|
dictionary.data[:Contents].each do |stream|
|
131
130
|
stream.compress_stream if document.compression_enabled?
|
132
|
-
stream.data[:Length] = stream.stream.size
|
133
131
|
end
|
134
132
|
else
|
135
133
|
content.compress_stream if document.compression_enabled?
|
136
|
-
content.data[:Length] = content.stream.size
|
137
134
|
end
|
138
135
|
end
|
139
136
|
|
@@ -160,7 +157,7 @@ module Prawn
|
|
160
157
|
|
161
158
|
def init_from_object(options)
|
162
159
|
@dictionary = options[:object_id].to_i
|
163
|
-
dictionary.data[:Parent] = document.state.store.pages
|
160
|
+
dictionary.data[:Parent] = document.state.store.pages if options[:page_template]
|
164
161
|
|
165
162
|
unless dictionary.data[:Contents].is_a?(Array) # content only on leafs
|
166
163
|
@content = dictionary.data[:Contents].identifier
|
@@ -175,7 +172,7 @@ module Prawn
|
|
175
172
|
@size = options[:size] || "LETTER"
|
176
173
|
@layout = options[:layout] || :portrait
|
177
174
|
|
178
|
-
@content = document.ref(
|
175
|
+
@content = document.ref({})
|
179
176
|
content << "q" << "\n"
|
180
177
|
@dictionary = document.ref(:Type => :Page,
|
181
178
|
:Parent => document.state.store.pages,
|
@@ -16,14 +16,21 @@ module Prawn
|
|
16
16
|
if "".respond_to?(:encode)
|
17
17
|
# Ruby 1.9+
|
18
18
|
def utf8_to_utf16(str)
|
19
|
-
"\xFE\xFF".force_encoding("UTF-16BE") + str.encode("UTF-16BE")
|
19
|
+
utf16 = "\xFE\xFF".force_encoding("UTF-16BE") + str.encode("UTF-16BE")
|
20
|
+
end
|
21
|
+
|
22
|
+
# encodes any string into a hex representation. The result is a string
|
23
|
+
# with only 0-9 and a-f characters. That result is valid ASCII so tag
|
24
|
+
# it as such to account for behaviour of different ruby VMs
|
25
|
+
def string_to_hex(str)
|
26
|
+
str.unpack("H*").first.force_encoding("ascii")
|
20
27
|
end
|
21
28
|
else
|
22
29
|
# Ruby 1.8
|
23
30
|
def utf8_to_utf16(str)
|
24
31
|
utf16 = "\xFE\xFF"
|
25
32
|
|
26
|
-
str.
|
33
|
+
str.codepoints do |cp|
|
27
34
|
if cp < 0x10000 # Basic Multilingual Plane
|
28
35
|
utf16 << [cp].pack("n")
|
29
36
|
else
|
@@ -36,6 +43,10 @@ module Prawn
|
|
36
43
|
|
37
44
|
utf16
|
38
45
|
end
|
46
|
+
|
47
|
+
def string_to_hex(str)
|
48
|
+
str.unpack("H*").first
|
49
|
+
end
|
39
50
|
end
|
40
51
|
|
41
52
|
# Serializes Ruby objects to their PDF equivalents. Most primitive objects
|
@@ -57,7 +68,13 @@ module Prawn
|
|
57
68
|
when NilClass then "null"
|
58
69
|
when TrueClass then "true"
|
59
70
|
when FalseClass then "false"
|
60
|
-
when Numeric
|
71
|
+
when Numeric
|
72
|
+
if (str = String(obj)) =~ /e/i
|
73
|
+
# scientific notation is not supported in PDF
|
74
|
+
sprintf("%.16f", obj).gsub(/\.?0+\z/, "")
|
75
|
+
else
|
76
|
+
str
|
77
|
+
end
|
61
78
|
when Array
|
62
79
|
"[" << obj.map { |e| PdfObject(e, in_content_stream) }.join(' ') << "]"
|
63
80
|
when Prawn::Core::LiteralString
|
@@ -71,7 +88,7 @@ module Prawn
|
|
71
88
|
"<" << obj.unpack("H*").first << ">"
|
72
89
|
when String
|
73
90
|
obj = utf8_to_utf16(obj) unless in_content_stream
|
74
|
-
"<" << obj
|
91
|
+
"<" << string_to_hex(obj) << ">"
|
75
92
|
when Symbol
|
76
93
|
"/" + obj.to_s.unpack("C*").map { |n|
|
77
94
|
if n < 33 || n > 126 || [35,40,41,47,60,62].include?(n)
|