prawn 1.0.0.rc2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +9 -0
  3. data/COPYING +2 -2
  4. data/Gemfile +8 -15
  5. data/LICENSE +1 -1
  6. data/Rakefile +25 -16
  7. data/data/images/16bit.alpha +0 -0
  8. data/data/images/16bit.color +0 -0
  9. data/data/images/dice.alpha +0 -0
  10. data/data/images/dice.color +0 -0
  11. data/data/images/indexed_color.dat +0 -0
  12. data/data/images/indexed_color.png +0 -0
  13. data/data/images/license.md +8 -0
  14. data/data/images/page_white_text.alpha +0 -0
  15. data/data/images/page_white_text.color +0 -0
  16. data/lib/prawn.rb +85 -23
  17. data/lib/prawn/document.rb +134 -116
  18. data/lib/prawn/document/bounding_box.rb +33 -4
  19. data/lib/prawn/document/column_box.rb +18 -6
  20. data/lib/prawn/document/graphics_state.rb +11 -74
  21. data/lib/prawn/document/internals.rb +24 -23
  22. data/lib/prawn/document/span.rb +12 -10
  23. data/lib/prawn/encoding.rb +8 -9
  24. data/lib/prawn/errors.rb +13 -32
  25. data/lib/prawn/font.rb +137 -105
  26. data/lib/prawn/font/afm.rb +76 -32
  27. data/lib/prawn/font/dfont.rb +4 -3
  28. data/lib/prawn/font/ttf.rb +33 -25
  29. data/lib/prawn/font_metric_cache.rb +47 -0
  30. data/lib/prawn/graphics.rb +177 -57
  31. data/lib/prawn/graphics/cap_style.rb +4 -3
  32. data/lib/prawn/graphics/color.rb +5 -4
  33. data/lib/prawn/graphics/dash.rb +53 -31
  34. data/lib/prawn/graphics/join_style.rb +9 -7
  35. data/lib/prawn/graphics/patterns.rb +4 -15
  36. data/lib/prawn/graphics/transformation.rb +10 -9
  37. data/lib/prawn/graphics/transparency.rb +3 -1
  38. data/lib/prawn/{layout/grid.rb → grid.rb} +72 -54
  39. data/lib/prawn/image_handler.rb +42 -0
  40. data/lib/prawn/images.rb +58 -54
  41. data/lib/prawn/images/image.rb +6 -22
  42. data/lib/prawn/images/jpg.rb +20 -14
  43. data/lib/prawn/images/png.rb +58 -121
  44. data/lib/prawn/layout.rb +12 -15
  45. data/lib/prawn/measurement_extensions.rb +10 -6
  46. data/lib/prawn/measurements.rb +27 -21
  47. data/lib/prawn/outline.rb +108 -147
  48. data/lib/prawn/repeater.rb +10 -8
  49. data/lib/prawn/security.rb +59 -40
  50. data/lib/prawn/security/arcfour.rb +52 -0
  51. data/lib/prawn/soft_mask.rb +4 -4
  52. data/lib/prawn/stamp.rb +5 -3
  53. data/lib/prawn/table.rb +83 -60
  54. data/lib/prawn/table/cell.rb +17 -21
  55. data/lib/prawn/table/cell/image.rb +2 -3
  56. data/lib/prawn/table/cell/in_table.rb +8 -2
  57. data/lib/prawn/table/cell/span_dummy.rb +5 -0
  58. data/lib/prawn/table/cell/subtable.rb +3 -2
  59. data/lib/prawn/table/cell/text.rb +14 -12
  60. data/lib/prawn/table/cells.rb +58 -14
  61. data/lib/prawn/table/column_width_calculator.rb +61 -0
  62. data/lib/prawn/text.rb +27 -26
  63. data/lib/prawn/text/box.rb +12 -6
  64. data/lib/prawn/text/formatted.rb +5 -4
  65. data/lib/prawn/text/formatted/arranger.rb +290 -0
  66. data/lib/prawn/text/formatted/box.rb +85 -57
  67. data/lib/prawn/text/formatted/fragment.rb +11 -11
  68. data/lib/prawn/text/formatted/line_wrap.rb +266 -0
  69. data/lib/prawn/text/formatted/parser.rb +11 -4
  70. data/lib/prawn/text/formatted/wrap.rb +156 -0
  71. data/lib/prawn/utilities.rb +5 -3
  72. data/manual/document_and_page_options/document_and_page_options.rb +2 -1
  73. data/manual/document_and_page_options/metadata.rb +3 -3
  74. data/manual/document_and_page_options/page_size.rb +2 -2
  75. data/manual/document_and_page_options/print_scaling.rb +20 -0
  76. data/manual/example_file.rb +2 -7
  77. data/manual/example_helper.rb +62 -81
  78. data/manual/graphics/common_lines.rb +2 -0
  79. data/manual/graphics/helper.rb +11 -4
  80. data/manual/graphics/stroke_dash.rb +19 -14
  81. data/manual/manual/cover.rb +16 -0
  82. data/manual/manual/manual.rb +1 -5
  83. data/manual/text/fallback_fonts.rb +4 -4
  84. data/manual/text/formatted_text.rb +5 -5
  85. data/manual/text/inline.rb +2 -4
  86. data/manual/text/registering_families.rb +12 -12
  87. data/manual/text/single_usage.rb +4 -4
  88. data/manual/text/text.rb +0 -2
  89. data/prawn.gemspec +21 -13
  90. data/spec/acceptance/png.rb +23 -0
  91. data/spec/annotations_spec.rb +16 -32
  92. data/spec/bounding_box_spec.rb +22 -5
  93. data/spec/cell_spec.rb +49 -5
  94. data/spec/column_box_spec.rb +32 -0
  95. data/spec/destinations_spec.rb +5 -5
  96. data/spec/document_spec.rb +112 -118
  97. data/spec/extensions/encoding_helpers.rb +5 -2
  98. data/spec/font_metric_cache_spec.rb +52 -0
  99. data/spec/font_spec.rb +121 -120
  100. data/spec/formatted_text_arranger_spec.rb +24 -24
  101. data/spec/formatted_text_box_spec.rb +31 -32
  102. data/spec/formatted_text_fragment_spec.rb +2 -2
  103. data/spec/graphics_spec.rb +63 -45
  104. data/spec/grid_spec.rb +24 -13
  105. data/spec/image_handler_spec.rb +54 -0
  106. data/spec/images_spec.rb +34 -21
  107. data/spec/inline_formatted_text_parser_spec.rb +69 -20
  108. data/spec/jpg_spec.rb +3 -3
  109. data/spec/line_wrap_spec.rb +25 -14
  110. data/spec/measurement_units_spec.rb +5 -5
  111. data/spec/outline_spec.rb +68 -64
  112. data/spec/png_spec.rb +15 -18
  113. data/spec/reference_spec.rb +2 -82
  114. data/spec/repeater_spec.rb +1 -1
  115. data/spec/security_spec.rb +41 -9
  116. data/spec/soft_mask_spec.rb +0 -40
  117. data/spec/span_spec.rb +6 -11
  118. data/spec/spec_helper.rb +20 -2
  119. data/spec/stamp_spec.rb +19 -20
  120. data/spec/stroke_styles_spec.rb +31 -13
  121. data/spec/table/span_dummy_spec.rb +17 -0
  122. data/spec/table_spec.rb +268 -43
  123. data/spec/text_at_spec.rb +13 -27
  124. data/spec/text_box_spec.rb +35 -30
  125. data/spec/text_spec.rb +56 -40
  126. data/spec/transparency_spec.rb +5 -5
  127. metadata +214 -217
  128. data/README.md +0 -98
  129. data/data/fonts/Action Man.dfont +0 -0
  130. data/data/fonts/Activa.ttf +0 -0
  131. data/data/fonts/Chalkboard.ttf +0 -0
  132. data/data/fonts/DejaVuSans.ttf +0 -0
  133. data/data/fonts/Dustismo_Roman.ttf +0 -0
  134. data/data/fonts/comicsans.ttf +0 -0
  135. data/data/fonts/gkai00mp.ttf +0 -0
  136. data/data/images/16bit.dat +0 -0
  137. data/data/images/barcode_issue.png +0 -0
  138. data/data/images/dice.dat +0 -0
  139. data/data/images/page_white_text.dat +0 -0
  140. data/data/images/rails.dat +0 -0
  141. data/data/images/rails.png +0 -0
  142. data/lib/prawn/compatibility.rb +0 -87
  143. data/lib/prawn/core.rb +0 -87
  144. data/lib/prawn/core/annotations.rb +0 -61
  145. data/lib/prawn/core/byte_string.rb +0 -9
  146. data/lib/prawn/core/destinations.rb +0 -90
  147. data/lib/prawn/core/document_state.rb +0 -79
  148. data/lib/prawn/core/literal_string.rb +0 -16
  149. data/lib/prawn/core/name_tree.rb +0 -177
  150. data/lib/prawn/core/object_store.rb +0 -320
  151. data/lib/prawn/core/page.rb +0 -212
  152. data/lib/prawn/core/pdf_object.rb +0 -125
  153. data/lib/prawn/core/reference.rb +0 -119
  154. data/lib/prawn/core/text.rb +0 -268
  155. data/lib/prawn/core/text/formatted/arranger.rb +0 -294
  156. data/lib/prawn/core/text/formatted/line_wrap.rb +0 -288
  157. data/lib/prawn/core/text/formatted/wrap.rb +0 -153
  158. data/lib/prawn/document/page_geometry.rb +0 -136
  159. data/lib/prawn/document/snapshot.rb +0 -89
  160. data/manual/manual/foreword.rb +0 -13
  161. data/manual/templates/full_template.rb +0 -23
  162. data/manual/templates/page_template.rb +0 -47
  163. data/manual/templates/templates.rb +0 -26
  164. data/manual/text/group.rb +0 -29
  165. data/spec/name_tree_spec.rb +0 -112
  166. data/spec/object_store_spec.rb +0 -170
  167. data/spec/pdf_object_spec.rb +0 -172
  168. data/spec/snapshot_spec.rb +0 -186
  169. data/spec/template_spec.rb +0 -351
@@ -1,89 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # snapshot.rb : Implements transactional rendering for Prawn
4
- #
5
- # Copyright August 2009, Brad Ediger. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
-
9
- require 'delegate'
10
-
11
- module Prawn
12
- class Document
13
- module Snapshot
14
-
15
- RollbackTransaction = Class.new(StandardError)
16
-
17
- # Call this within a +transaction+ block to roll back the transaction and
18
- # prevent any of its data from being rendered. You must reset the
19
- # y-position yourself if you have performed any drawing operations that
20
- # modify it.
21
- #
22
- def rollback
23
- raise RollbackTransaction
24
- end
25
-
26
- # Run a block of drawing operations, to be completed atomically. If
27
- # +rollback+ is called or a RollbackTransaction exception is raised
28
- # inside the block, all actions taken inside the block will be rolled
29
- # back (with the exception of y-position, which you must restore
30
- # yourself).
31
- #
32
- # Returns true on success, or false if the transaction was rolled back.
33
- #
34
- def transaction
35
- snap = take_snapshot
36
- yield
37
- true
38
- rescue RollbackTransaction
39
- restore_snapshot(snap)
40
- false
41
- end
42
-
43
- private
44
-
45
- # Takes a current snapshot of the document's state, sufficient to
46
- # reconstruct it after it was amended.
47
- #
48
- def take_snapshot
49
- # current_page holds a ref to the Pages dictionary which grows
50
- # monotonically as data is added to the document, so we share that
51
- # between the old and new copies.
52
- {:page_content => state.page.content.deep_copy,
53
- :current_page => state.page.dictionary.deep_copy(share=[:Parent]),
54
- :bounds => bounds.deep_copy,
55
- :page_number => page_number,
56
- :page_kids => state.store.pages.data[:Kids].compact.map{|kid| kid.identifier},
57
- :dests => names? && names.data[:Dests].deep_copy}
58
- end
59
-
60
- # Rolls the page state back to the state of the given snapshot.
61
- #
62
- def restore_snapshot(shot)
63
- page = state.page
64
- # Because these objects are referenced by identifier from the Pages
65
- # dictionary, we can't just restore them over the current refs in
66
- # page_content and current_page. We have to restore them over the old
67
- # ones.
68
- page.content = shot[:page_content].identifier
69
- page.content.replace shot[:page_content]
70
-
71
- page.dictionary = shot[:current_page].identifier
72
- page.dictionary.replace shot[:current_page]
73
- page.dictionary.data[:Contents] = page.content
74
-
75
- self.page_number = shot[:page_number]
76
-
77
- state.store.pages.data[:Kids] = shot[:page_kids].map{|id| state.store[id]}
78
- state.store.pages.data[:Count] = shot[:page_kids].size
79
-
80
- self.bounds = BoundingBox.restore_deep_copy(shot[:bounds], self)
81
-
82
- if shot[:dests]
83
- names.data[:Dests] = shot[:dests]
84
- end
85
- end
86
-
87
- end
88
- end
89
- end
@@ -1,13 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- # Prawn manual foreword page.
4
- #
5
- require File.expand_path(File.join(File.dirname(__FILE__),
6
- %w[.. example_helper]))
7
-
8
- filename = File.basename(__FILE__).gsub('.rb', '.pdf')
9
- Prawn::Example.generate(filename) do
10
- header("Foreword, by Gregory Brown")
11
- prose "This will be written just before 1.0, to give the" +
12
- " core team something to look forward to."
13
- end
@@ -1,23 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- # You may load another PDF while creating a new one. Just pass the loaded PDF
4
- # filename to the <code>:template</code> option when creating/generating the new
5
- # PDF.
6
- #
7
- # The provided PDF will be loaded and the its first page will be set as the
8
- # current page. If you'd like to resume the document you may take advantage of
9
- # two helpers: <code>page_count</code> and <code>go_to_page</code>.
10
- #
11
- require File.expand_path(File.join(File.dirname(__FILE__),
12
- %w[.. example_helper]))
13
-
14
- filename = "#{Prawn::DATADIR}/pdfs/multipage_template.pdf"
15
-
16
- Prawn::Example.generate("full_template.pdf", :template => filename) do
17
- go_to_page(page_count)
18
-
19
- start_new_page
20
-
21
- text "Previous pages and content imported.", :align => :center
22
- text "This page and content is brand new.", :align => :center
23
- end
@@ -1,47 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- # If you only need to load some pages from another PDF, you can accomplish it
4
- # with the <code>start_new_page</code> method. You may pass it a
5
- # <code>:template</code> option with the path for an existing pdf and a
6
- # <code>:template_page</code> option to specify which page to load.
7
- # You can also load a <code>:template</code> using a URI:
8
- #
9
- # <code>require 'open-uri'</code>
10
- #
11
- # <code>start_new_page(:template => open('url_for_your.pdf'))</code>
12
- #
13
- # The following example loads some pages from an existing PDF. If we don't
14
- # specify the <code>:template_page</code> option, the first page of the template
15
- # PDF will be loaded. That's what happens on the first load below. Then we load
16
- # a page by specifying the <code>:template_page</code> option and then we do it
17
- # again this time adding some content to the loaded page.
18
- #
19
- require File.expand_path(File.join(File.dirname(__FILE__),
20
- %w[.. example_helper]))
21
-
22
- filename = File.basename(__FILE__).gsub('.rb', '.pdf')
23
- Prawn::Example.generate(filename) do
24
- text "Please scan the next 3 pages to see the page templates in action."
25
- move_down 10
26
- text "You also might want to look at the pdf used as a template: "
27
- url = "https://github.com/prawnpdf/prawn/raw/master/data/pdfs/form.pdf"
28
- move_down 10
29
-
30
- formatted_text [{:text => url, :link => url}]
31
-
32
- filename = "#{Prawn::DATADIR}/pdfs/form.pdf"
33
- start_new_page(:template => filename)
34
-
35
- start_new_page(:template => filename, :template_page => 2)
36
-
37
- start_new_page(:template => filename, :template_page => 2)
38
-
39
- fill_color "FF8888"
40
-
41
- text_box "John Doe", :at => [75, cursor-75]
42
- text_box "john@doe.com", :at => [75, cursor-105]
43
- text_box "John Doe inc", :at => [75, cursor-135]
44
- text_box "You didn't think I'd tell, did you?", :at => [75, cursor-165]
45
-
46
- fill_color "000000"
47
- end
@@ -1,26 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- # Examples for loading existing pdfs.
4
- #
5
- require File.expand_path(File.join(File.dirname(__FILE__),
6
- %w[.. example_helper]))
7
-
8
- Prawn::Example.generate("templates.pdf", :page_size => "FOLIO") do
9
-
10
- package "templates" do |p|
11
-
12
- p.example "full_template", :eval_source => false, :full_source => true
13
- p.example "page_template"
14
-
15
- p.intro do
16
- prose("Templates let you embed other PDF documents inside the current one.
17
-
18
- The examples show:")
19
-
20
- list( "How to load the whole content from another PDF",
21
- "How to load single pages from another PDF"
22
- )
23
- end
24
-
25
- end
26
- end
@@ -1,29 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- # Sometimes free flowing text might look ugly, specially when a paragraph is
4
- # split between two pages. Using a positioned text box just to overcome this
5
- # nuisance is not the right choice.
6
- #
7
- # You probably want to use the <code>group</code> method instead. It will try
8
- # to render the block within the current page. If the content would fall to a
9
- # new page it just renders everything on the following page. If the block cannot
10
- # be executed on a single blank page a <code>CannotGroup</code> exception will
11
- # be raised.
12
- #
13
- # So if you can split your text blocks in paragraphs you can have every
14
- # paragraph contained on a single page.
15
- #
16
- require File.expand_path(File.join(File.dirname(__FILE__),
17
- %w[.. example_helper]))
18
-
19
- filename = File.basename(__FILE__).gsub('.rb', '.pdf')
20
- Prawn::Example.generate(filename) do
21
- move_cursor_to 80
22
- text "Let's move to the end of the page so that you can see group in action."
23
-
24
- group do
25
- text "This block of text was too big to be rendered on the bottom of the " +
26
- " previous page. So it was rendered entirely on this new page. " +
27
- " _ " * 200
28
- end
29
- end
@@ -1,112 +0,0 @@
1
- require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
2
-
3
- def tree_dump(tree)
4
- if tree.is_a?(Prawn::Core::NameTree::Node)
5
- "[" + tree.children.map { |child| tree_dump(child) }.join(",") + "]"
6
- else
7
- "#{tree.name}=#{tree.value}"
8
- end
9
- end
10
-
11
- def tree_add(tree, *args)
12
- args.each do |(name, value)|
13
- tree.add(name, value)
14
- end
15
- end
16
-
17
- def tree_value(name, value)
18
- Prawn::Core::NameTree::Value.new(name, value)
19
- end
20
-
21
- class RefExposingDocument < Prawn::Document
22
- def object_store
23
- state.store
24
- end
25
- end
26
-
27
- describe "Name Tree" do
28
- before(:each) { create_pdf(RefExposingDocument) }
29
-
30
- it "should have no children when first initialized" do
31
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
32
- node.children.length.should == 0
33
- end
34
-
35
- it "should have no subtrees while child limit is not reached" do
36
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
37
- tree_add(node, ["one", 1], ["two", 2], ["three", 3])
38
- tree_dump(node).should == "[one=1,three=3,two=2]"
39
- end
40
-
41
- it "should split into subtrees when limit is exceeded" do
42
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
43
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
44
- tree_dump(node).should == "[[four=4,one=1],[three=3,two=2]]"
45
- end
46
-
47
- it "should create a two new references when root is split" do
48
- ref_count = @pdf.object_store.length
49
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
50
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
51
- @pdf.object_store.length.should == ref_count+2
52
- end
53
-
54
- it "should create a one new reference when subtree is split" do
55
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
56
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
57
-
58
- ref_count = @pdf.object_store.length # save when root is split
59
- tree_add(node, ["five", 5], ["six", 6], ["seven", 7])
60
- tree_dump(node).should == "[[five=5,four=4,one=1],[seven=7,six=6],[three=3,two=2]]"
61
- @pdf.object_store.length.should == ref_count+1
62
- end
63
-
64
- it "should keep tree balanced when subtree split cascades to root" do
65
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
66
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
67
- tree_add(node, ["five", 5], ["six", 6], ["seven", 7], ["eight", 8])
68
- tree_dump(node).should == "[[[eight=8,five=5],[four=4,one=1]],[[seven=7,six=6],[three=3,two=2]]]"
69
- end
70
-
71
- it "should maintain order of already properly ordered nodes" do
72
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
73
- tree_add(node, ["eight", 8], ["five", 5], ["four", 4], ["one", 1])
74
- tree_add(node, ['seven', 7], ['six', 6], ['three', 3], ['two', 2])
75
- tree_dump(node).should == "[[[eight=8,five=5],[four=4,one=1]],[[seven=7,six=6],[three=3,two=2]]]"
76
- end
77
-
78
- it "should emit only :Names key with to_hash if root is only node" do
79
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
80
- tree_add(node, ["one", 1], ["two", 2], ["three", 3])
81
- node.to_hash.should ==(
82
- { :Names => [tree_value("one", 1), tree_value("three", 3), tree_value("two", 2)] }
83
- )
84
- end
85
-
86
- it "should emit only :Kids key with to_hash if root has children" do
87
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
88
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
89
- node.to_hash.should ==({ :Kids => node.children.map { |child| child.ref } })
90
- end
91
-
92
- it "should emit :Limits and :Names keys with to_hash for leaf node" do
93
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
94
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
95
- node.children.first.to_hash.should ==(
96
- { :Limits => %w(four one),
97
- :Names => [tree_value("four", 4), tree_value("one", 1)] }
98
- )
99
- end
100
-
101
- it "should emit :Limits and :Kids keys with to_hash for inner node" do
102
- node = Prawn::Core::NameTree::Node.new(@pdf, 3)
103
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
104
- tree_add(node, ["five", 5], ["six", 6], ["seven", 7], ["eight", 8])
105
- tree_add(node, ["nine", 9], ["ten", 10], ["eleven", 11], ["twelve", 12])
106
- tree_add(node, ["thirteen", 13], ["fourteen", 14], ["fifteen", 15], ["sixteen", 16])
107
- node.children.first.to_hash.should ==(
108
- { :Limits => %w(eight one),
109
- :Kids => node.children.first.children.map { |child| child.ref } }
110
- )
111
- end
112
- end
@@ -1,170 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
-
5
- describe "Prawn::ObjectStore" do
6
- before(:each) do
7
- @store = Prawn::Core::ObjectStore.new
8
- end
9
-
10
- it "should create required roots by default, including info passed to new" do
11
- store = Prawn::Core::ObjectStore.new(:info => {:Test => 3})
12
- store.size.should == 3 # 3 default roots
13
- store.info.data[:Test].should == 3
14
- store.pages.data[:Count].should == 0
15
- store.root.data[:Pages].should == store.pages
16
- end
17
-
18
- it "should import objects from an existing PDF" do
19
- filename = "#{Prawn::BASEDIR}/spec/data/curves.pdf"
20
- store = Prawn::Core::ObjectStore.new(:template => filename)
21
- store.size.should == 5
22
- end
23
-
24
- it "should point to existing roots when importing objects from an existing PDF" do
25
- filename = "#{Prawn::BASEDIR}/spec/data/curves.pdf"
26
- store = Prawn::Core::ObjectStore.new(:template => filename)
27
- store.info.class.should == Prawn::Core::Reference
28
- store.root.class.should == Prawn::Core::Reference
29
- end
30
-
31
- it "should initialize with pages when importing objects from an existing PDF" do
32
- filename = "#{Prawn::BASEDIR}/spec/data/curves.pdf"
33
- store = Prawn::Core::ObjectStore.new(:template => filename)
34
- store.pages.data[:Count].should == 1
35
- end
36
-
37
- it "should import all objects from a PDF that has an indirect reference in a stream dict" do
38
- filename = "#{Prawn::DATADIR}/pdfs/indirect_reference.pdf"
39
- store = Prawn::Core::ObjectStore.new(:template => filename)
40
- store.size.should == 8
41
- end
42
-
43
- it "should raise_error ArgumentError when given a file that doesn exist as a template" do
44
- filename = "not_really_there.pdf"
45
-
46
- lambda { Prawn::Core::ObjectStore.new(:template => filename) }.should raise_error(ArgumentError)
47
- end
48
-
49
- it "should raise_error Prawn::Errors::TemplateError when given a non PDF as a template" do
50
- filename = "#{Prawn::DATADIR}/images/dice.png"
51
-
52
- lambda { Prawn::Core::ObjectStore.new(:template => filename) }.should raise_error(Prawn::Errors::TemplateError)
53
- end
54
-
55
- it "should raise_error Prawn::Errors::TemplateError when given an encrypted PDF as a template" do
56
- filename = "#{Prawn::DATADIR}/pdfs/encrypted.pdf"
57
-
58
- lambda { Prawn::Core::ObjectStore.new(:template => filename) }.should raise_error(Prawn::Errors::TemplateError)
59
- end
60
-
61
- it "should add to its objects when ref() is called" do
62
- count = @store.size
63
- @store.ref("blah")
64
- @store.size.should == count + 1
65
- end
66
-
67
- it "should accept push with a Prawn::Reference" do
68
- r = Prawn::Core::Reference(123, "blah")
69
- @store.push(r)
70
- @store[r.identifier].should == r
71
- end
72
-
73
- it "should accept arbitrary data and use it to create a Prawn::Reference" do
74
- @store.push(123, "blahblah")
75
- @store[123].data.should == "blahblah"
76
- end
77
-
78
- it "should be Enumerable, yielding in order of submission" do
79
- # higher IDs to bypass the default roots
80
- [10, 11, 12].each do |id|
81
- @store.push(id, "some data #{id}")
82
- end
83
- @store.map{|ref| ref.identifier}[-3..-1].should == [10, 11, 12]
84
- end
85
- end
86
-
87
- describe "Prawn::ObjectStore#compact" do
88
- it "should do nothing to an ObjectStore with all live refs" do
89
- store = Prawn::Core::ObjectStore.new
90
- store.info.data[:Blah] = store.ref(:some => "structure")
91
- old_size = store.size
92
- store.compact
93
-
94
- store.size.should == old_size
95
- end
96
-
97
- it "should remove dead objects, renumbering live objects from 1" do
98
- store = Prawn::Core::ObjectStore.new
99
- store.ref(:some => "structure")
100
- old_size = store.size
101
- store.compact
102
-
103
- store.size.should be < old_size
104
- store.map{ |o| o.identifier }.should == (1..store.size).to_a
105
- end
106
-
107
- it "should detect and remove dead objects that were once live" do
108
- store = Prawn::Core::ObjectStore.new
109
- store.info.data[:Blah] = store.ref(:some => "structure")
110
- store.info.data[:Blah] = :overwritten
111
- old_size = store.size
112
- store.compact
113
-
114
- store.size.should be < old_size
115
- store.map{ |o| o.identifier }.should == (1..store.size).to_a
116
- end
117
- end
118
-
119
- describe "Prawn::ObjectStorie#object_id_for_page" do
120
- it "should return the object ID of an imported template page" do
121
- filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
122
- store = Prawn::Core::ObjectStore.new(:template => filename)
123
- store.object_id_for_page(0).should == 4
124
- end
125
-
126
- it "should return the object ID of the first imported template page" do
127
- filename = "#{Prawn::DATADIR}/pdfs/two_hexagons.pdf"
128
- store = Prawn::Core::ObjectStore.new(:template => filename)
129
- store.object_id_for_page(1).should == 4
130
- end
131
-
132
- it "should return the object ID of the last imported template page" do
133
- filename = "#{Prawn::DATADIR}/pdfs/two_hexagons.pdf"
134
- store = Prawn::Core::ObjectStore.new(:template => filename)
135
- store.object_id_for_page(-1).should == 6
136
- end
137
-
138
- it "should return the object ID of the first page of a template that uses nested Pages" do
139
- filename = "#{Prawn::DATADIR}/pdfs/nested_pages.pdf"
140
- store = Prawn::Core::ObjectStore.new(:template => filename)
141
- store.object_id_for_page(1).should == 5
142
- end
143
-
144
- it "should return the object ID of the last page of a template that uses nested Pages" do
145
- filename = "#{Prawn::DATADIR}/pdfs/nested_pages.pdf"
146
- store = Prawn::Core::ObjectStore.new(:template => filename)
147
- store.object_id_for_page(-1).should == 8
148
- end
149
-
150
- it "should return nil if given an invalid page number" do
151
- filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
152
- store = Prawn::Core::ObjectStore.new(:template => filename)
153
- store.object_id_for_page(10).should == nil
154
- end
155
-
156
- it "should return nil if given an invalid page number" do
157
- store = Prawn::Core::ObjectStore.new
158
- store.object_id_for_page(10).should == nil
159
- end
160
-
161
- it "should accept a stream instead of a filename" do
162
- example = Prawn::Document.new()
163
- example.text "An example doc, created in memory"
164
- example.start_new_page
165
- StringIO.open(example.render) do |stream|
166
- @pdf = Prawn::Core::ObjectStore.new(:template => stream)
167
- end
168
- @pdf.page_count.should == 2
169
- end
170
- end