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,20 +1,17 @@
1
- require "prawn/table"
2
- require 'prawn/layout/grid'
1
+ # This is free software. Please see the LICENSE and COPYING files for details.
3
2
 
4
- module Prawn
5
-
6
- module Errors
7
-
8
- # This error is raised when table data is malformed
9
- #
10
- InvalidTableData = Class.new(StandardError)
3
+ require_relative "table"
4
+ require_relative "grid"
11
5
 
12
- # This error is raised when an empty or nil table is rendered
13
- #
14
- EmptyTable = Class.new(StandardError)
15
- end
6
+ module Prawn
7
+ module Errors
16
8
 
17
- module Layout
9
+ # This error is raised when table data is malformed
10
+ #
11
+ InvalidTableData = Class.new(StandardError)
18
12
 
19
- end
13
+ # This error is raised when an empty or nil table is rendered
14
+ #
15
+ EmptyTable = Class.new(StandardError)
16
+ end
20
17
  end
@@ -5,13 +5,17 @@
5
5
  #
6
6
  # This is free software. Please see the LICENSE and COPYING files for details.
7
7
 
8
- require 'prawn/measurements'
8
+ require_relative 'measurements'
9
+
10
+ # @group Stable API
9
11
 
10
12
  class Numeric
11
- include Prawn::Measurements
12
- # prawns' basic unit is PostScript-Point
13
+ include Prawn::Measurements
14
+ # prawns' basic unit is PostScript-Point
13
15
  # 72 points per inch
14
16
 
17
+ # @group Experimental API
18
+
15
19
  def mm
16
20
  return mm2pt(self)
17
21
  end
@@ -39,8 +43,8 @@ class Numeric
39
43
  def ft
40
44
  return ft2pt(self)
41
45
  end
42
-
46
+
43
47
  def pt
44
- return self
48
+ return pt2pt(self)
45
49
  end
46
- end
50
+ end
@@ -3,69 +3,75 @@
3
3
  #
4
4
  # Copyright December 2008, Florian Witteler. All Rights Reserved.
5
5
  #
6
- module Prawn
6
+ module Prawn
7
+ # @group Stable API
8
+
7
9
  module Measurements
8
-
10
+
9
11
  # ============================================================================
10
12
  #metric conversions
11
13
  def cm2mm(cm)
12
14
  return cm*10
13
15
  end
14
-
16
+
15
17
  def dm2mm(dm)
16
- return dm*100
18
+ return dm*100
17
19
  end
18
-
20
+
19
21
  def m2mm(m)
20
22
  return m*1000
21
23
  end
22
-
24
+
23
25
  # ============================================================================
24
- # imperial conversions
26
+ # imperial conversions
25
27
  # from http://en.wikipedia.org/wiki/Imperial_units
26
-
28
+
27
29
  def ft2in(ft)
28
30
  return ft * 12
29
- end
31
+ end
30
32
 
31
33
  def yd2in(yd)
32
34
  return yd*36
33
35
  end
34
36
 
35
-
37
+
36
38
  # ============================================================================
37
39
  # PostscriptPoint-converisons
38
-
40
+
41
+ def pt2pt(pt)
42
+ return pt
43
+ end
44
+
39
45
  def in2pt(inch)
40
- return inch * 72
46
+ return inch * 72
41
47
  end
42
-
48
+
43
49
  def ft2pt(ft)
44
50
  return in2pt(ft2in(ft))
45
51
  end
46
-
52
+
47
53
  def yd2pt(yd)
48
54
  return in2pt(yd2in(yd))
49
55
  end
50
-
56
+
51
57
  def mm2pt(mm)
52
58
  return mm*(72 / 25.4)
53
59
  end
54
-
60
+
55
61
  def cm2pt(cm)
56
62
  return mm2pt(cm2mm(cm))
57
63
  end
58
-
64
+
59
65
  def dm2pt(dm)
60
66
  return mm2pt(dm2mm(dm))
61
67
  end
62
-
68
+
63
69
  def m2pt(m)
64
70
  return mm2pt(m2mm(m))
65
71
  end
66
-
67
- def pt2mm(pt)
72
+
73
+ def pt2mm(pt)
68
74
  return pt * 1 / mm2pt(1)# (25.4 / 72)
69
75
  end
70
76
  end
71
- end
77
+ end
@@ -1,57 +1,49 @@
1
- # encoding: utf-8
2
- #
3
- # generates outline dictionary and items for document
4
- #
5
- # Author Jonathan Greenberg
6
-
7
- require 'forwardable'
8
-
9
1
  module Prawn
10
-
11
2
  class Document
12
-
13
- # Lazily instantiates an Outline object for document. This is used as point of entry
14
- # to methods to build the outline tree.
3
+ # @group Stable API
4
+
5
+ # Lazily instantiates a Prawn::Outline object for document. This is used as point of entry
6
+ # to methods to build the outline tree for a document's table of contents.
15
7
  def outline
16
8
  @outline ||= Outline.new(self)
17
- end
18
-
9
+ end
19
10
  end
20
-
11
+
21
12
  # The Outline class organizes the outline tree items for the document.
22
- # Note that the prev and parent instance variables are adjusted while navigating
23
- # through the nested blocks. These variables along with the presence or absense
13
+ # Note that the prev and parent instance variables are adjusted while navigating
14
+ # through the nested blocks. These variables along with the presence or absense
24
15
  # of blocks are the primary means by which the relations for the various
25
16
  # OutlineItems and the OutlineRoot are set. Unfortunately, the best way to
26
17
  # understand how this works is to follow the method calls through a real example.
27
18
  #
28
- # Some ideas for the organization of this class were gleaned from name_tree. In
29
- # particular the way in which the OutlineItems are finally rendered into document
19
+ # Some ideas for the organization of this class were gleaned from name_tree. In
20
+ # particular the way in which the OutlineItems are finally rendered into document
30
21
  # objects in PdfObject through a hash.
31
22
  #
32
23
  class Outline
33
-
34
- extend Forwardable
35
- def_delegator :@document, :page_number
36
-
37
- attr_accessor :parent
38
- attr_accessor :prev
39
- attr_accessor :document
40
- attr_accessor :items
41
-
24
+ # @private
25
+ attr_accessor :parent, :prev, :document, :items
26
+
42
27
  def initialize(document)
43
28
  @document = document
44
29
  @parent = root
45
30
  @prev = nil
46
31
  @items = {}
47
- end
48
-
32
+ end
33
+
34
+ # @group Stable API
35
+
36
+ # Returns the current page number of the document
37
+ def page_number
38
+ @document.page_number
39
+ end
40
+
49
41
  # Defines/Updates an outline for the document.
50
- # The outline is an optional nested index that appears on the side of a PDF
51
- # document usually with direct links to pages. The outline DSL is defined by nested
52
- # blocks involving two methods: section and page; see the documentation on those methods
53
- # for their arguments and options. Note that one can also use outline#update
54
- # to add more sections to the end of the outline tree using the same syntax and scope.
42
+ # The outline is an optional nested index that appears on the side of a PDF
43
+ # document usually with direct links to pages. The outline DSL is defined by nested
44
+ # blocks involving two methods: section and page; see the documentation on those methods
45
+ # for their arguments and options. Note that one can also use outline#update
46
+ # to add more sections to the end of the outline tree using the same syntax and scope.
55
47
  #
56
48
  # The syntax is best illustrated with an example:
57
49
  #
@@ -61,107 +53,109 @@ module Prawn
61
53
  # text "Page 2. More in the first Chapter. "
62
54
  # start_new_page
63
55
  # outline.define do
64
- # section 'Chapter 1', :destination => 1, :closed => true do
56
+ # section 'Chapter 1', :destination => 1, :closed => true do
65
57
  # page :destination => 1, :title => 'Page 1'
66
58
  # page :destination => 2, :title => 'Page 2'
67
59
  # end
68
- # end
60
+ # end
69
61
  # start_new_page do
70
- # outline.update do
62
+ # outline.update do
71
63
  # section 'Chapter 2', :destination => 2, do
72
64
  # page :destination => 3, :title => 'Page 3'
73
65
  # end
74
66
  # end
75
- # end
67
+ # end
76
68
  #
77
69
  def define(&block)
78
70
  instance_eval(&block) if block
79
71
  end
80
-
81
- alias :update :define
82
-
72
+
73
+ alias :update :define
74
+
83
75
  # Inserts an outline section to the outline tree (see outline#define).
84
- # Although you will probably choose to exclusively use outline#define so
76
+ # Although you will probably choose to exclusively use outline#define so
85
77
  # that your outline tree is contained and easy to manage, this method
86
78
  # gives you the option to insert sections to the outline tree at any point
87
- # during document generation. This method allows you to add a child subsection
88
- # to any other item at any level in the outline tree.
89
- # Currently the only way to locate the place of entry is with the title for the
79
+ # during document generation. This method allows you to add a child subsection
80
+ # to any other item at any level in the outline tree.
81
+ # Currently the only way to locate the place of entry is with the title for the
90
82
  # item. If your title names are not unique consider using define_outline.
91
83
  # The method takes the following arguments:
92
84
  # title: a string that must match an outline title to add the subsection to
93
- # position: either :first or :last(the default) where the subsection will be placed relative
94
- # to other child elements. If you need to position your subsection in between
95
- # other elements then consider using #insert_section_after
96
- # block: uses the same DSL syntax as outline#define, for example:
85
+ # position: either :first or :last(the default) where the subsection will be placed relative
86
+ # to other child elements. If you need to position your subsection in between
87
+ # other elements then consider using #insert_section_after
88
+ # block: uses the same DSL syntax as outline#define, for example:
97
89
  #
98
90
  # Consider using this method inside of outline.update if you want to have the outline object
99
91
  # to be scoped as self (see #insert_section_after example).
100
- #
92
+ #
101
93
  # go_to_page 2
102
94
  # start_new_page
103
95
  # text "Inserted Page"
104
- # outline.add_subsection_to :title => 'Page 2', :first do
96
+ # outline.add_subsection_to :title => 'Page 2', :first do
105
97
  # outline.page :destination => page_number, :title => "Inserted Page"
106
98
  # end
107
- #
99
+ #
108
100
  def add_subsection_to(title, position = :last, &block)
109
101
  @parent = items[title]
110
- raise Prawn::Errors::UnknownOutlineTitle,
102
+ raise Prawn::Errors::UnknownOutlineTitle,
111
103
  "\n No outline item with title: '#{title}' exists in the outline tree" unless @parent
112
104
  @prev = position == :first ? nil : @parent.data.last
113
105
  nxt = position == :first ? @parent.data.first : nil
114
- insert_section(nxt, &block)
106
+ insert_section(nxt, &block)
115
107
  end
116
-
108
+
117
109
  # Inserts an outline section to the outline tree (see outline#define).
118
- # Although you will probably choose to exclusively use outline#define so
110
+ # Although you will probably choose to exclusively use outline#define so
119
111
  # that your outline tree is contained and easy to manage, this method
120
112
  # gives you the option to insert sections to the outline tree at any point
121
- # during document generation. Unlike outline.add_section, this method allows
122
- # you to enter a section after any other item at any level in the outline tree.
123
- # Currently the only way to locate the place of entry is with the title for the
113
+ # during document generation. Unlike outline.add_section, this method allows
114
+ # you to enter a section after any other item at any level in the outline tree.
115
+ # Currently the only way to locate the place of entry is with the title for the
124
116
  # item. If your title names are not unique consider using define_outline.
125
117
  # The method takes the following arguments:
126
118
  # title: the title of other section or page to insert new section after
127
- # block: uses the same DSL syntax as outline#define, for example:
128
- #
119
+ # block: uses the same DSL syntax as outline#define, for example:
120
+ #
129
121
  # go_to_page 2
130
122
  # start_new_page
131
123
  # text "Inserted Page"
132
124
  # update_outline do
133
- # insert_section_after :title => 'Page 2' do
134
- # page :destination => page_number, :title => "Inserted Page"
125
+ # insert_section_after :title => 'Page 2' do
126
+ # page :destination => page_number, :title => "Inserted Page"
135
127
  # end
136
128
  # end
137
129
  #
138
130
  def insert_section_after(title, &block)
139
131
  @prev = items[title]
140
- raise Prawn::Errors::UnknownOutlineTitle,
132
+ raise Prawn::Errors::UnknownOutlineTitle,
141
133
  "\n No outline item with title: '#{title}' exists in the outline tree" unless @prev
142
134
  @parent = @prev.data.parent
143
135
  nxt = @prev.data.next
144
- insert_section(nxt, &block)
136
+ insert_section(nxt, &block)
145
137
  end
146
-
138
+
147
139
  # See outline#define above for documentation on how this is used in that context
148
140
  #
149
141
  # Adds an outine section to the outline tree.
150
- # Although you will probably choose to exclusively use outline#define so
142
+ # Although you will probably choose to exclusively use outline#define so
151
143
  # that your outline tree is contained and easy to manage, this method
152
144
  # gives you the option to add sections to the outline tree at any point
153
- # during document generation. When not being called from within another #section block
154
- # the section will be added at the top level after the other root elements of the outline.
155
- # For more flexible placement try using outline#insert_section_after and/or
156
- # outline#add_subsection_to
145
+ # during document generation. When not being called from within another #section block
146
+ # the section will be added at the top level after the other root elements of the outline.
147
+ # For more flexible placement try using outline#insert_section_after and/or
148
+ # outline#add_subsection_to
157
149
  # Takes the following arguments:
158
150
  # title: the outline text that appears for the section.
159
- # options: destination - optional integer defining the page number for a destination link.
160
- # - currently only :FIT destination supported with link to top of page.
151
+ # options: destination - optional integer defining the page number for a destination link
152
+ # to the top of the page (using a :FIT destination).
153
+ # - or an array with a custom destination (see the #dest_* methods of the
154
+ # PDF::Destination module)
161
155
  # closed - whether the section should show its nested outline elements.
162
- # - defaults to false.
163
- # block: more nested subsections and/or page blocks
164
- #
156
+ # - defaults to false.
157
+ # block: more nested subsections and/or page blocks
158
+ #
165
159
  # example usage:
166
160
  #
167
161
  # outline.section 'Added Section', :destination => 3 do
@@ -169,49 +163,51 @@ module Prawn
169
163
  # end
170
164
  def section(title, options = {}, &block)
171
165
  add_outline_item(title, options, &block)
172
- end
173
-
166
+ end
167
+
174
168
  # See Outline#define above for more documentation on how it is used in that context
175
169
  #
176
170
  # Adds a page to the outline.
177
- # Although you will probably choose to exclusively use outline#define so
171
+ # Although you will probably choose to exclusively use outline#define so
178
172
  # that your outline tree is contained and easy to manage, this method also
179
173
  # gives you the option to add pages to the root of outline tree at any point
180
- # during document generation. Note that the page will be added at the
174
+ # during document generation. Note that the page will be added at the
181
175
  # top level after the other root outline elements. For more flexible placement try
182
176
  # using outline#insert_section_after and/or outline#add_subsection_to.
183
- #
177
+ #
184
178
  # Takes the following arguments:
185
179
  # options:
186
- # title - REQUIRED. The outline text that appears for the page.
187
- # destination - integer defining the page number for the destination link.
188
- # currently only :FIT destination supported with link to top of page.
180
+ # title - REQUIRED. The outline text that appears for the page.
181
+ # destination - optional integer defining the page number for a destination link
182
+ # to the top of the page (using a :FIT destination).
183
+ # - or an array with a custom destination (see the #dest_* methods of the
184
+ # PDF::Destination module)
189
185
  # closed - whether the section should show its nested outline elements.
190
186
  # - defaults to false.
191
187
  # example usage:
192
188
  #
193
- # outline.page :title => "Very Last Page"
194
- # Note: this method is almost identical to section except that it does not accept a block
195
- # thereby defining the outline item as a leaf on the outline tree structure.
189
+ # outline.page :title => "Very Last Page"
190
+ # Note: this method is almost identical to section except that it does not accept a block
191
+ # thereby defining the outline item as a leaf on the outline tree structure.
196
192
  def page(options = {})
197
193
  if options[:title]
198
- title = options[:title]
194
+ title = options[:title]
199
195
  else
200
- raise Prawn::Errors::RequiredOption,
196
+ raise Prawn::Errors::RequiredOption,
201
197
  "\nTitle is a required option for page"
202
198
  end
203
199
  add_outline_item(title, options)
204
200
  end
205
-
206
- private
207
-
201
+
202
+ private
203
+
208
204
  # The Outline dictionary (12.3.3) for this document. It is
209
205
  # lazily initialized, so that documents that do not have an outline
210
206
  # do not incur the additional overhead.
211
207
  def root
212
- document.state.store.root.data[:Outlines] ||= document.ref!(OutlineRoot.new)
208
+ document.state.store.root.data[:Outlines] ||= document.ref!(PDF::Core::OutlineRoot.new)
213
209
  end
214
-
210
+
215
211
  def add_outline_item(title, options, &block)
216
212
  outline_item = create_outline_item(title, options)
217
213
  set_relations(outline_item)
@@ -220,25 +216,28 @@ module Prawn
220
216
  block.call if block
221
217
  reset_parent(outline_item)
222
218
  end
223
-
219
+
224
220
  def create_outline_item(title, options)
225
- outline_item = OutlineItem.new(title, parent, options)
221
+ outline_item = PDF::Core::OutlineItem.new(title, parent, options)
226
222
 
227
- if options[:destination]
223
+ case options[:destination]
224
+ when Integer
228
225
  page_index = options[:destination] - 1
229
- outline_item.dest = [document.state.pages[page_index].dictionary, :Fit]
226
+ outline_item.dest = [document.state.pages[page_index].dictionary, :Fit]
227
+ when Array
228
+ outline_item.dest = options[:destination]
230
229
  end
231
230
 
232
231
  outline_item.prev = prev if @prev
233
232
  items[title] = document.ref!(outline_item)
234
233
  end
235
-
234
+
236
235
  def set_relations(outline_item)
237
236
  prev.data.next = outline_item if prev
238
237
  parent.data.first = outline_item unless prev
239
238
  parent.data.last = outline_item
240
239
  end
241
-
240
+
242
241
  def increase_count
243
242
  counting_parent = parent
244
243
  while counting_parent
@@ -250,19 +249,19 @@ module Prawn
250
249
  end
251
250
  end
252
251
  end
253
-
252
+
254
253
  def set_variables_for_block(outline_item, block)
255
254
  self.prev = block ? nil : outline_item
256
255
  self.parent = outline_item if block
257
256
  end
258
-
257
+
259
258
  def reset_parent(outline_item)
260
259
  if parent == outline_item
261
260
  self.prev = outline_item
262
261
  self.parent = outline_item.data.parent
263
262
  end
264
- end
265
-
263
+ end
264
+
266
265
  def insert_section(nxt, &block)
267
266
  last = @parent.data.last
268
267
  if block
@@ -271,56 +270,18 @@ module Prawn
271
270
  adjust_relations(nxt, last)
272
271
  reset_root_positioning
273
272
  end
274
-
273
+
275
274
  def adjust_relations(nxt, last)
276
- if nxt
275
+ if nxt
277
276
  nxt.data.prev = @prev
278
277
  @prev.data.next = nxt
279
278
  @parent.data.last = last
280
279
  end
281
- end
282
-
280
+ end
281
+
283
282
  def reset_root_positioning
284
283
  @parent = root
285
284
  @prev = root.data.last
286
285
  end
287
-
288
286
  end
289
-
290
- class OutlineRoot #:nodoc:
291
- attr_accessor :count, :first, :last
292
-
293
- def initialize
294
- @count = 0
295
- end
296
-
297
- def to_hash
298
- {:Type => :Outlines, :Count => count, :First => first, :Last => last}
299
- end
300
- end
301
-
302
- class OutlineItem #:nodoc:
303
- attr_accessor :count, :first, :last, :next, :prev, :parent, :title, :dest, :closed
304
-
305
- def initialize(title, parent, options)
306
- @closed = options[:closed]
307
- @title = title
308
- @parent = parent
309
- @count = 0
310
- end
311
-
312
- def to_hash
313
- hash = { :Title => title,
314
- :Parent => parent,
315
- :Count => closed ? -count : count }
316
- [{:First => first}, {:Last => last}, {:Next => @next},
317
- {:Prev => prev}, {:Dest => dest}].each do |h|
318
- unless h.values.first.nil?
319
- hash.merge!(h)
320
- end
321
- end
322
- hash
323
- end
324
- end
325
287
  end
326
-