giga-fast-kit 0.0.1

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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/giga-fast-kit.gemspec +12 -0
  3. data/prawn-2.5.0/COPYING +2 -0
  4. data/prawn-2.5.0/GPLv2 +339 -0
  5. data/prawn-2.5.0/GPLv3 +674 -0
  6. data/prawn-2.5.0/LICENSE +56 -0
  7. data/prawn-2.5.0/data/fonts/Courier-Bold.afm +342 -0
  8. data/prawn-2.5.0/data/fonts/Courier-BoldOblique.afm +342 -0
  9. data/prawn-2.5.0/data/fonts/Courier-Oblique.afm +342 -0
  10. data/prawn-2.5.0/data/fonts/Courier.afm +342 -0
  11. data/prawn-2.5.0/data/fonts/Helvetica-Bold.afm +2827 -0
  12. data/prawn-2.5.0/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  13. data/prawn-2.5.0/data/fonts/Helvetica-Oblique.afm +3051 -0
  14. data/prawn-2.5.0/data/fonts/Helvetica.afm +3051 -0
  15. data/prawn-2.5.0/data/fonts/MustRead.html +19 -0
  16. data/prawn-2.5.0/data/fonts/Symbol.afm +213 -0
  17. data/prawn-2.5.0/data/fonts/Times-Bold.afm +2588 -0
  18. data/prawn-2.5.0/data/fonts/Times-BoldItalic.afm +2384 -0
  19. data/prawn-2.5.0/data/fonts/Times-Italic.afm +2667 -0
  20. data/prawn-2.5.0/data/fonts/Times-Roman.afm +2419 -0
  21. data/prawn-2.5.0/data/fonts/ZapfDingbats.afm +225 -0
  22. data/prawn-2.5.0/lib/prawn/document/bounding_box.rb +625 -0
  23. data/prawn-2.5.0/lib/prawn/document/column_box.rb +177 -0
  24. data/prawn-2.5.0/lib/prawn/document/internals.rb +76 -0
  25. data/prawn-2.5.0/lib/prawn/document/span.rb +65 -0
  26. data/prawn-2.5.0/lib/prawn/document.rb +846 -0
  27. data/prawn-2.5.0/lib/prawn/encoding.rb +85 -0
  28. data/prawn-2.5.0/lib/prawn/errors.rb +73 -0
  29. data/prawn-2.5.0/lib/prawn/font.rb +567 -0
  30. data/prawn-2.5.0/lib/prawn/font_metric_cache.rb +50 -0
  31. data/prawn-2.5.0/lib/prawn/fonts/afm.rb +332 -0
  32. data/prawn-2.5.0/lib/prawn/fonts/dfont.rb +42 -0
  33. data/prawn-2.5.0/lib/prawn/fonts/otf.rb +14 -0
  34. data/prawn-2.5.0/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
  35. data/prawn-2.5.0/lib/prawn/fonts/ttc.rb +41 -0
  36. data/prawn-2.5.0/lib/prawn/fonts/ttf.rb +615 -0
  37. data/prawn-2.5.0/lib/prawn/fonts.rb +14 -0
  38. data/prawn-2.5.0/lib/prawn/graphics/blend_mode.rb +62 -0
  39. data/prawn-2.5.0/lib/prawn/graphics/cap_style.rb +44 -0
  40. data/prawn-2.5.0/lib/prawn/graphics/color.rb +257 -0
  41. data/prawn-2.5.0/lib/prawn/graphics/dash.rb +123 -0
  42. data/prawn-2.5.0/lib/prawn/graphics/join_style.rb +60 -0
  43. data/prawn-2.5.0/lib/prawn/graphics/patterns.rb +389 -0
  44. data/prawn-2.5.0/lib/prawn/graphics/transformation.rb +172 -0
  45. data/prawn-2.5.0/lib/prawn/graphics/transparency.rb +79 -0
  46. data/prawn-2.5.0/lib/prawn/graphics.rb +791 -0
  47. data/prawn-2.5.0/lib/prawn/grid.rb +449 -0
  48. data/prawn-2.5.0/lib/prawn/image_handler.rb +61 -0
  49. data/prawn-2.5.0/lib/prawn/images/image.rb +48 -0
  50. data/prawn-2.5.0/lib/prawn/images/jpg.rb +121 -0
  51. data/prawn-2.5.0/lib/prawn/images/png.rb +383 -0
  52. data/prawn-2.5.0/lib/prawn/images.rb +195 -0
  53. data/prawn-2.5.0/lib/prawn/measurement_extensions.rb +82 -0
  54. data/prawn-2.5.0/lib/prawn/measurements.rb +129 -0
  55. data/prawn-2.5.0/lib/prawn/outline.rb +316 -0
  56. data/prawn-2.5.0/lib/prawn/repeater.rb +140 -0
  57. data/prawn-2.5.0/lib/prawn/security/arcfour.rb +54 -0
  58. data/prawn-2.5.0/lib/prawn/security.rb +308 -0
  59. data/prawn-2.5.0/lib/prawn/soft_mask.rb +105 -0
  60. data/prawn-2.5.0/lib/prawn/stamp.rb +147 -0
  61. data/prawn-2.5.0/lib/prawn/text/box.rb +192 -0
  62. data/prawn-2.5.0/lib/prawn/text/formatted/arranger.rb +396 -0
  63. data/prawn-2.5.0/lib/prawn/text/formatted/box.rb +725 -0
  64. data/prawn-2.5.0/lib/prawn/text/formatted/fragment.rb +373 -0
  65. data/prawn-2.5.0/lib/prawn/text/formatted/line_wrap.rb +335 -0
  66. data/prawn-2.5.0/lib/prawn/text/formatted/parser.rb +284 -0
  67. data/prawn-2.5.0/lib/prawn/text/formatted/wrap.rb +166 -0
  68. data/prawn-2.5.0/lib/prawn/text/formatted.rb +82 -0
  69. data/prawn-2.5.0/lib/prawn/text.rb +701 -0
  70. data/prawn-2.5.0/lib/prawn/transformation_stack.rb +63 -0
  71. data/prawn-2.5.0/lib/prawn/utilities.rb +34 -0
  72. data/prawn-2.5.0/lib/prawn/version.rb +6 -0
  73. data/prawn-2.5.0/lib/prawn/view.rb +116 -0
  74. data/prawn-2.5.0/lib/prawn.rb +83 -0
  75. metadata +114 -0
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop: disable Naming/MethodParameterName
4
+ module Prawn
5
+ # @group Stable API
6
+
7
+ # Distance unit conversions between metric, imperial, and PDF.
8
+ module Measurements
9
+ # metric conversions
10
+
11
+ # Convert centimeter to millimeters.
12
+ #
13
+ # @param cm [Number]
14
+ # @return [Number]
15
+ def cm2mm(cm)
16
+ cm * 10
17
+ end
18
+
19
+ # Convert decimeters to millimeters.
20
+ #
21
+ # @param dm [Number]
22
+ # @return [Number]
23
+ def dm2mm(dm)
24
+ dm * 100
25
+ end
26
+
27
+ # Convert meters to millimeters.
28
+ #
29
+ # @param m [Number]
30
+ # @return [Number]
31
+ def m2mm(m)
32
+ m * 1000
33
+ end
34
+
35
+ # imperial conversions
36
+ # from http://en.wikipedia.org/wiki/Imperial_units
37
+
38
+ # Convert feet to inches.
39
+ #
40
+ # @param ft [Number]
41
+ # @return [Number]
42
+ def ft2in(ft)
43
+ ft * 12
44
+ end
45
+
46
+ # Convert yards to inches.
47
+ #
48
+ # @param yd [Number]
49
+ # @return [Number]
50
+ def yd2in(yd)
51
+ yd * 36
52
+ end
53
+
54
+ # PostscriptPoint-converisons
55
+
56
+ # Convert points to points. For completeness.
57
+ #
58
+ # @param pt [Number]
59
+ # @return [Number]
60
+ def pt2pt(pt)
61
+ pt
62
+ end
63
+
64
+ # Convert inches to points.
65
+ #
66
+ # @param inch [Number]
67
+ # @return [Number]
68
+ def in2pt(inch)
69
+ inch * 72
70
+ end
71
+
72
+ # Convert feet to points.
73
+ #
74
+ # @param ft [Number]
75
+ # @return [Number]
76
+ def ft2pt(ft)
77
+ in2pt(ft2in(ft))
78
+ end
79
+
80
+ # Convert yards to points.
81
+ #
82
+ # @param yd [Number]
83
+ # @return [Number]
84
+ def yd2pt(yd)
85
+ in2pt(yd2in(yd))
86
+ end
87
+
88
+ # Convert millimeters to points.
89
+ #
90
+ # @param mm [Number]
91
+ # @return [Number]
92
+ def mm2pt(mm)
93
+ mm * (72 / 25.4)
94
+ end
95
+
96
+ # Convert centimeters to points.
97
+ #
98
+ # @param cm [Number]
99
+ # @return [Number]
100
+ def cm2pt(cm)
101
+ mm2pt(cm2mm(cm))
102
+ end
103
+
104
+ # Convert decimeters to points.
105
+ #
106
+ # @param dm [Number]
107
+ # @return [Number]
108
+ def dm2pt(dm)
109
+ mm2pt(dm2mm(dm))
110
+ end
111
+
112
+ # Convert meters to points.
113
+ #
114
+ # @param m [Number]
115
+ # @return [Number]
116
+ def m2pt(m)
117
+ mm2pt(m2mm(m))
118
+ end
119
+
120
+ # Convert points to millimeters.
121
+ #
122
+ # @param pt [Number]
123
+ # @return [Number]
124
+ def pt2mm(pt)
125
+ pt * 1 / mm2pt(1) # (25.4 / 72)
126
+ end
127
+ end
128
+ end
129
+ # rubocop: enable Naming/MethodParameterName
@@ -0,0 +1,316 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prawn
4
+ class Document # rubocop: disable Style/Documentation
5
+ # @group Stable API
6
+
7
+ # Lazily instantiates a Prawn::Outline object for document. This is used as
8
+ # point of entry to methods to build the outline tree for a document's table
9
+ # of contents.
10
+ #
11
+ # @return [Prawn::Outline]
12
+ def outline
13
+ @outline ||= Outline.new(self)
14
+ end
15
+ end
16
+
17
+ # The Outline class organizes the outline tree items for the document. Note
18
+ # that the {prev} and {parent} are adjusted while navigating through the
19
+ # nested blocks. These attributes along with the presence or absence of blocks
20
+ # are the primary means by which the relations for the various
21
+ # `PDF::Core::OutlineItem`s and the `PDF::Core::OutlineRoot` are set.
22
+ #
23
+ # Some ideas for the organization of this class were gleaned from `name_tree`.
24
+ # In particular the way in which the `PDF::Core::OutlineItem`s are finally
25
+ # rendered into document objects through a hash.
26
+ class Outline
27
+ # @private
28
+ attr_accessor :parent, :prev, :document, :items
29
+
30
+ # @param document [Prawn::Document]
31
+ def initialize(document)
32
+ @document = document
33
+ @parent = root
34
+ @prev = nil
35
+ @items = {}
36
+ end
37
+
38
+ # @group Stable API
39
+
40
+ # Returns the current page number of the document.
41
+ #
42
+ # @return [Integer]
43
+ def page_number
44
+ @document.page_number
45
+ end
46
+
47
+ # Defines/Updates an outline for the document.
48
+ #
49
+ # The outline is an optional nested index that appears on the side of a PDF
50
+ # document usually with direct links to pages. The outline DSL is defined by
51
+ # nested blocks involving two methods: {section} and {page}. Note that one
52
+ # can also use {update} to add more sections to the end of the outline tree
53
+ # using the same syntax and scope.
54
+ #
55
+ # The syntax is best illustrated with an example:
56
+ #
57
+ # ```ruby
58
+ # Prawn::Document.generate('outlined_document.pdf') do
59
+ # text "Page 1. This is the first Chapter. "
60
+ # start_new_page
61
+ # text "Page 2. More in the first Chapter. "
62
+ # start_new_page
63
+ # outline.define do
64
+ # section 'Chapter 1', destination: 1, closed: true do
65
+ # page destination: 1, title: 'Page 1'
66
+ # page destination: 2, title: 'Page 2'
67
+ # end
68
+ # end
69
+ # start_new_page do
70
+ # outline.update do
71
+ # section 'Chapter 2', destination: 2, do
72
+ # page destination: 3, title: 'Page 3'
73
+ # end
74
+ # end
75
+ # end
76
+ # ```
77
+ #
78
+ # @yield
79
+ # @return [void]
80
+ def define(&block)
81
+ instance_eval(&block) if block
82
+ end
83
+
84
+ alias update define
85
+
86
+ # Inserts an outline section to the outline tree (see {define}).
87
+ #
88
+ # Although you will probably choose to exclusively use {define} so that your
89
+ # outline tree is contained and easy to manage, this method gives you the
90
+ # option to insert sections to the outline tree at any point during document
91
+ # generation. This method allows you to add a child subsection to any other
92
+ # item at any level in the outline tree. Currently the only way to locate
93
+ # the place of entry is with the title for the item. If your title names are
94
+ # not unique consider using {define}.
95
+ #
96
+ # Consider using this method instead of {update} if you want to have the
97
+ # outline object to be scoped as self (see {insert_section_after} example).
98
+ #
99
+ # ```ruby
100
+ # go_to_page 2
101
+ # start_new_page
102
+ # text "Inserted Page"
103
+ # outline.add_subsection_to title: 'Page 2', :first do
104
+ # outline.page destination: page_number, title: "Inserted Page"
105
+ # end
106
+ # ```
107
+ #
108
+ # @param title [String] An outline title to add the subsection to.
109
+ # @param position [:first, :last] (:last)
110
+ # Where the subsection will be placed relative to other child elements. If
111
+ # you need to position your subsection in between other elements then
112
+ # consider using {insert_section_after}.
113
+ # @yield Uses the same DSL syntax as {define}
114
+ # @return [void]
115
+ def add_subsection_to(title, position = :last, &block)
116
+ @parent = items[title]
117
+ unless @parent
118
+ raise Prawn::Errors::UnknownOutlineTitle,
119
+ "\n No outline item with title: '#{title}' exists in the outline tree"
120
+ end
121
+ @prev = position == :first ? nil : @parent.data.last
122
+ nxt = position == :first ? @parent.data.first : nil
123
+ insert_section(nxt, &block)
124
+ end
125
+
126
+ # Inserts an outline section to the outline tree (see {define}).
127
+ #
128
+ # Although you will probably choose to exclusively use {define} so that your
129
+ # outline tree is contained and easy to manage, this method gives you the
130
+ # option to insert sections to the outline tree at any point during document
131
+ # generation. Unlike {add_subsection_to}, this method allows you to enter
132
+ # a section after any other item at any level in the outline tree.
133
+ # Currently the only way to locate the place of entry is with the title for
134
+ # the item. If your title names are not unique consider using
135
+ # {define}.
136
+ #
137
+ # @example
138
+ # go_to_page 2
139
+ # start_new_page
140
+ # text "Inserted Page"
141
+ # update_outline do
142
+ # insert_section_after :title => 'Page 2' do
143
+ # page :destination => page_number, :title => "Inserted Page"
144
+ # end
145
+ # end
146
+ #
147
+ # @param title [String]
148
+ # The title of other section or page to insert new section after.
149
+ # @yield Uses the same DSL syntax as {define}.
150
+ # @return [void]
151
+ def insert_section_after(title, &block)
152
+ @prev = items[title]
153
+ unless @prev
154
+ raise Prawn::Errors::UnknownOutlineTitle,
155
+ "\n No outline item with title: '#{title}' exists in the outline tree"
156
+ end
157
+ @parent = @prev.data.parent
158
+ nxt = @prev.data.next
159
+ insert_section(nxt, &block)
160
+ end
161
+
162
+ # Adds an outline section to the outline tree.
163
+ #
164
+ # Although you will probably choose to exclusively use {define} so that your
165
+ # outline tree is contained and easy to manage, this method gives you the
166
+ # option to add sections to the outline tree at any point during document
167
+ # generation. When not being called from within another {section} block the
168
+ # section will be added at the top level after the other root elements of
169
+ # the outline. For more flexible placement try using {insert_section_after}
170
+ # and/or {add_subsection_to}.
171
+ #
172
+ # @example
173
+ # outline.section 'Added Section', destination: 3 do
174
+ # outline.page destionation: 3, title: 'Page 3'
175
+ # end
176
+ #
177
+ # @param title [String] The outline text that appears for the section.
178
+ # @param options [Hash{Symbol => any}]
179
+ # @option options :destination [Integer, Array]
180
+ # - Optional page number for a destination link to the top of the page
181
+ # (using a `:FIT` destination).
182
+ # - An array with a custom destination (see the `#dest_*` methods of the
183
+ # `PDF::Core::Destination` module).
184
+ # @option options :closed [Boolean] (false)
185
+ # Whether the section should show its nested outline elements.
186
+ # @yield More nested subsections and/or page blocks.
187
+ # @return [void]
188
+ def section(title, options = {}, &block)
189
+ add_outline_item(title, options, &block)
190
+ end
191
+
192
+ # Adds a page to the outline.
193
+ #
194
+ # Although you will probably choose to exclusively use {define} so that your
195
+ # outline tree is contained and easy to manage, this method also gives you
196
+ # the option to add pages to the root of outline tree at any point during
197
+ # document generation. Note that the page will be added at the top level
198
+ # after the other root outline elements. For more flexible placement try
199
+ # using {insert_section_after} and/or {add_subsection_to}.
200
+ #
201
+ # @note This method is almost identical to {section} except that it does not
202
+ # accept a block thereby defining the outline item as a leaf on the
203
+ # outline tree structure.
204
+ #
205
+ # @example
206
+ # outline.page title: "Very Last Page"
207
+ #
208
+ # @param options [Hash{Symbol => any}]
209
+ # @option options :title [String] REQUIRED.
210
+ # The outline text that appears for the page.
211
+ # @option options :destination [Integer, Array]
212
+ # - The page number for a destination link to the top of the page (using
213
+ # a `:FIT` destination).
214
+ # - An array with a custom destination (see the `#dest_*` methods of the
215
+ # `PDF::Core::Destination` module).
216
+ # @option options :closed [Boolean] (false)
217
+ # Whether the section should show its nested outline elements.
218
+ # @return [void]
219
+ def page(options = {})
220
+ if options[:title]
221
+ title = options[:title]
222
+ else
223
+ raise Prawn::Errors::RequiredOption,
224
+ "\nTitle is a required option for page"
225
+ end
226
+ add_outline_item(title, options)
227
+ end
228
+
229
+ private
230
+
231
+ # The Outline dictionary (12.3.3) for this document. It is
232
+ # lazily initialized, so that documents that do not have an outline
233
+ # do not incur the additional overhead.
234
+ def root
235
+ document.state.store.root.data[:Outlines] ||=
236
+ document.ref!(PDF::Core::OutlineRoot.new)
237
+ end
238
+
239
+ def add_outline_item(title, options, &block)
240
+ outline_item = create_outline_item(title, options)
241
+ establish_relations(outline_item)
242
+ increase_count
243
+ set_variables_for_block(outline_item, block)
244
+ yield if block
245
+ reset_parent(outline_item)
246
+ end
247
+
248
+ def create_outline_item(title, options)
249
+ outline_item = PDF::Core::OutlineItem.new(title, parent, options)
250
+
251
+ case options[:destination]
252
+ when Integer
253
+ page_index = options[:destination] - 1
254
+ outline_item.dest = [document.state.pages[page_index].dictionary, :Fit]
255
+ when Array
256
+ outline_item.dest = options[:destination]
257
+ end
258
+
259
+ outline_item.prev = prev if @prev
260
+ items[title] = document.ref!(outline_item)
261
+ end
262
+
263
+ def establish_relations(outline_item)
264
+ prev.data.next = outline_item if prev
265
+ parent.data.first = outline_item unless prev
266
+ parent.data.last = outline_item
267
+ end
268
+
269
+ def increase_count
270
+ counting_parent = parent
271
+ while counting_parent
272
+ counting_parent.data.count += 1
273
+ counting_parent =
274
+ if counting_parent == root
275
+ nil
276
+ else
277
+ counting_parent.data.parent
278
+ end
279
+ end
280
+ end
281
+
282
+ def set_variables_for_block(outline_item, block)
283
+ self.prev = block ? nil : outline_item
284
+ self.parent = outline_item if block
285
+ end
286
+
287
+ def reset_parent(outline_item)
288
+ if parent == outline_item
289
+ self.prev = outline_item
290
+ self.parent = outline_item.data.parent
291
+ end
292
+ end
293
+
294
+ def insert_section(nxt, &block)
295
+ last = @parent.data.last
296
+ if block
297
+ yield
298
+ end
299
+ adjust_relations(nxt, last)
300
+ reset_root_positioning
301
+ end
302
+
303
+ def adjust_relations(nxt, last)
304
+ if nxt
305
+ nxt.data.prev = @prev
306
+ @prev.data.next = nxt
307
+ @parent.data.last = last
308
+ end
309
+ end
310
+
311
+ def reset_root_positioning
312
+ @parent = root
313
+ @prev = root.data.last
314
+ end
315
+ end
316
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prawn
4
+ class Document # rubocop: disable Style/Documentation
5
+ # A list of all repeaters in the document.
6
+ # See {repeat} for details.
7
+ #
8
+ # @private
9
+ # @return [Array]
10
+ def repeaters
11
+ @repeaters ||= []
12
+ end
13
+
14
+ # @group Experimental API
15
+
16
+ # Provides a way to execute a block of code repeatedly based on
17
+ # a `page_filter`. Since Stamp is used under the hood, this method is very
18
+ # space efficient.
19
+ #
20
+ # Also accepts an optional second argument for dynamic content which
21
+ # executes the code in the context of the filtered pages without using
22
+ # a Stamp.
23
+ #
24
+ # @example
25
+ # Prawn::Document.generate("repeat.pdf", skip_page_creation: true) do
26
+ # repeat :all do
27
+ # draw_text "ALLLLLL", at: bounds.top_left
28
+ # end
29
+ #
30
+ # repeat :odd do
31
+ # draw_text "ODD", at: [0, 0]
32
+ # end
33
+ #
34
+ # repeat :even do
35
+ # draw_text "EVEN", at: [0, 0]
36
+ # end
37
+ #
38
+ # repeat [1, 2] do
39
+ # draw_text "[1, 2]", at: [100, 0]
40
+ # end
41
+ #
42
+ # repeat 2..4 do
43
+ # draw_text "2..4", at: [200, 0]
44
+ # end
45
+ #
46
+ # repeat(lambda { |pg| pg % 3 == 0 }) do
47
+ # draw_text "Every third", at: [250, 20]
48
+ # end
49
+ #
50
+ # 10.times do
51
+ # start_new_page
52
+ # draw_text "A wonderful page", at: [400, 400]
53
+ # end
54
+ #
55
+ # repeat(:all, dynamic: true) do
56
+ # text page_number, at: [500, 0]
57
+ # end
58
+ # end
59
+ #
60
+ # @param page_filter [:all, :odd, :even, Array<Integer>, Range, Proc]
61
+ # Pages to draw the repeater content on.
62
+ #
63
+ # Available page filters are:
64
+ #
65
+ # - `:all` -- repeats on every page.
66
+ # - `:odd` -- repeats on odd pages.
67
+ # - `:even` -- repeats on even pages.
68
+ # - Array of Integers -- repeats on every page listed in the array.
69
+ # - Range -- repeats on every page included in the range.
70
+ # - Proc -- yields page number and repeats for true return values.
71
+ # @param options [Hash]
72
+ # @option options :dynamic [Boolean] (false)
73
+ # A dynamic repeater executes block on every matched page. A static
74
+ # repeater uses {stamp} to prepare the content (runs the block once) and
75
+ # puts it on every matched page.
76
+ # @return [void]
77
+ def repeat(page_filter, options = {}, &block)
78
+ dynamic = options.fetch(:dynamic, false)
79
+ repeaters << Prawn::Repeater.new(
80
+ self, page_filter, dynamic, &block
81
+ )
82
+ end
83
+ end
84
+
85
+ # Repeater object.
86
+ #
87
+ # @private
88
+ class Repeater
89
+ class << self
90
+ attr_writer :count
91
+
92
+ # Repeater counter.
93
+ #
94
+ # It's not an exact number of repeaters but a counter used to generate
95
+ # unique repeater stamp names.
96
+ #
97
+ # @return [Integer]
98
+ def count
99
+ @count ||= 0
100
+ end
101
+ end
102
+
103
+ attr_reader :name
104
+
105
+ def initialize(document, page_filter, dynamic = false, &block)
106
+ @document = document
107
+ @page_filter = page_filter
108
+ @dynamic = dynamic
109
+ @stamp_name = "prawn_repeater(#{Repeater.count})"
110
+ @document.create_stamp(@stamp_name, &block) unless dynamic
111
+ @block = block if dynamic
112
+ @graphic_state = document.state.page.graphic_state.dup
113
+
114
+ Repeater.count += 1
115
+ end
116
+
117
+ # Should this repeater run on this page?
118
+ #
119
+ # @param page_number [Integer]
120
+ # @return [Boolean]
121
+ def match?(page_number)
122
+ @document.page_match?(@page_filter, page_number)
123
+ end
124
+
125
+ # Run repeater.
126
+ #
127
+ # @param page_number [Integer]
128
+ # @return [void]
129
+ def run(page_number)
130
+ if !@dynamic
131
+ @document.stamp(@stamp_name) if match?(page_number)
132
+ elsif @block && match?(page_number)
133
+ @document.save_graphics_state(@graphic_state) do
134
+ @document.__send__(:freeze_stamp_graphics)
135
+ @block.call
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Implementation of the "ARCFOUR" algorithm ("alleged RC4 (tm)"). Implemented
4
+ # as described at:
5
+ # http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt
6
+ #
7
+ # "RC4" is a trademark of RSA Data Security, Inc.
8
+ #
9
+ # @private
10
+ class Arcfour
11
+ def initialize(key)
12
+ # Convert string key to Array of integers
13
+ key = key.unpack('c*') if key.is_a?(String)
14
+
15
+ # 1. Allocate an 256 element array of 8 bit bytes to be used as an S-box
16
+ # 2. Initialize the S-box. Fill each entry first with it's index
17
+ @sbox = (0..255).to_a
18
+
19
+ # 3. Fill another array of the same size (256) with the key, repeating
20
+ # bytes as necessary.
21
+ s2 = []
22
+ while s2.length < 256
23
+ s2 += key
24
+ end
25
+ s2 = s2[0, 256]
26
+
27
+ # 4. Set j to zero and initialize the S-box
28
+ j = 0
29
+ (0..255).each do |i|
30
+ j = (j + @sbox[i] + s2[i]) % 256
31
+ @sbox[i], @sbox[j] = @sbox[j], @sbox[i]
32
+ end
33
+
34
+ @i = @j = 0
35
+ end
36
+
37
+ # Encrypt string.
38
+ #
39
+ # @param string [String]
40
+ # @return [String]
41
+ def encrypt(string)
42
+ string.unpack('c*').map { |byte| byte ^ key_byte }.pack('c*')
43
+ end
44
+
45
+ private
46
+
47
+ # Produces the next byte of key material in the stream (3.2 Stream Generation)
48
+ def key_byte
49
+ @i = (@i + 1) % 256
50
+ @j = (@j + @sbox[@i]) % 256
51
+ @sbox[@i], @sbox[@j] = @sbox[@j], @sbox[@i]
52
+ @sbox[(@sbox[@i] + @sbox[@j]) % 256]
53
+ end
54
+ end