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.
- checksums.yaml +7 -0
- data/giga-fast-kit.gemspec +12 -0
- data/prawn-2.5.0/COPYING +2 -0
- data/prawn-2.5.0/GPLv2 +339 -0
- data/prawn-2.5.0/GPLv3 +674 -0
- data/prawn-2.5.0/LICENSE +56 -0
- data/prawn-2.5.0/data/fonts/Courier-Bold.afm +342 -0
- data/prawn-2.5.0/data/fonts/Courier-BoldOblique.afm +342 -0
- data/prawn-2.5.0/data/fonts/Courier-Oblique.afm +342 -0
- data/prawn-2.5.0/data/fonts/Courier.afm +342 -0
- data/prawn-2.5.0/data/fonts/Helvetica-Bold.afm +2827 -0
- data/prawn-2.5.0/data/fonts/Helvetica-BoldOblique.afm +2827 -0
- data/prawn-2.5.0/data/fonts/Helvetica-Oblique.afm +3051 -0
- data/prawn-2.5.0/data/fonts/Helvetica.afm +3051 -0
- data/prawn-2.5.0/data/fonts/MustRead.html +19 -0
- data/prawn-2.5.0/data/fonts/Symbol.afm +213 -0
- data/prawn-2.5.0/data/fonts/Times-Bold.afm +2588 -0
- data/prawn-2.5.0/data/fonts/Times-BoldItalic.afm +2384 -0
- data/prawn-2.5.0/data/fonts/Times-Italic.afm +2667 -0
- data/prawn-2.5.0/data/fonts/Times-Roman.afm +2419 -0
- data/prawn-2.5.0/data/fonts/ZapfDingbats.afm +225 -0
- data/prawn-2.5.0/lib/prawn/document/bounding_box.rb +625 -0
- data/prawn-2.5.0/lib/prawn/document/column_box.rb +177 -0
- data/prawn-2.5.0/lib/prawn/document/internals.rb +76 -0
- data/prawn-2.5.0/lib/prawn/document/span.rb +65 -0
- data/prawn-2.5.0/lib/prawn/document.rb +846 -0
- data/prawn-2.5.0/lib/prawn/encoding.rb +85 -0
- data/prawn-2.5.0/lib/prawn/errors.rb +73 -0
- data/prawn-2.5.0/lib/prawn/font.rb +567 -0
- data/prawn-2.5.0/lib/prawn/font_metric_cache.rb +50 -0
- data/prawn-2.5.0/lib/prawn/fonts/afm.rb +332 -0
- data/prawn-2.5.0/lib/prawn/fonts/dfont.rb +42 -0
- data/prawn-2.5.0/lib/prawn/fonts/otf.rb +14 -0
- data/prawn-2.5.0/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
- data/prawn-2.5.0/lib/prawn/fonts/ttc.rb +41 -0
- data/prawn-2.5.0/lib/prawn/fonts/ttf.rb +615 -0
- data/prawn-2.5.0/lib/prawn/fonts.rb +14 -0
- data/prawn-2.5.0/lib/prawn/graphics/blend_mode.rb +62 -0
- data/prawn-2.5.0/lib/prawn/graphics/cap_style.rb +44 -0
- data/prawn-2.5.0/lib/prawn/graphics/color.rb +257 -0
- data/prawn-2.5.0/lib/prawn/graphics/dash.rb +123 -0
- data/prawn-2.5.0/lib/prawn/graphics/join_style.rb +60 -0
- data/prawn-2.5.0/lib/prawn/graphics/patterns.rb +389 -0
- data/prawn-2.5.0/lib/prawn/graphics/transformation.rb +172 -0
- data/prawn-2.5.0/lib/prawn/graphics/transparency.rb +79 -0
- data/prawn-2.5.0/lib/prawn/graphics.rb +791 -0
- data/prawn-2.5.0/lib/prawn/grid.rb +449 -0
- data/prawn-2.5.0/lib/prawn/image_handler.rb +61 -0
- data/prawn-2.5.0/lib/prawn/images/image.rb +48 -0
- data/prawn-2.5.0/lib/prawn/images/jpg.rb +121 -0
- data/prawn-2.5.0/lib/prawn/images/png.rb +383 -0
- data/prawn-2.5.0/lib/prawn/images.rb +195 -0
- data/prawn-2.5.0/lib/prawn/measurement_extensions.rb +82 -0
- data/prawn-2.5.0/lib/prawn/measurements.rb +129 -0
- data/prawn-2.5.0/lib/prawn/outline.rb +316 -0
- data/prawn-2.5.0/lib/prawn/repeater.rb +140 -0
- data/prawn-2.5.0/lib/prawn/security/arcfour.rb +54 -0
- data/prawn-2.5.0/lib/prawn/security.rb +308 -0
- data/prawn-2.5.0/lib/prawn/soft_mask.rb +105 -0
- data/prawn-2.5.0/lib/prawn/stamp.rb +147 -0
- data/prawn-2.5.0/lib/prawn/text/box.rb +192 -0
- data/prawn-2.5.0/lib/prawn/text/formatted/arranger.rb +396 -0
- data/prawn-2.5.0/lib/prawn/text/formatted/box.rb +725 -0
- data/prawn-2.5.0/lib/prawn/text/formatted/fragment.rb +373 -0
- data/prawn-2.5.0/lib/prawn/text/formatted/line_wrap.rb +335 -0
- data/prawn-2.5.0/lib/prawn/text/formatted/parser.rb +284 -0
- data/prawn-2.5.0/lib/prawn/text/formatted/wrap.rb +166 -0
- data/prawn-2.5.0/lib/prawn/text/formatted.rb +82 -0
- data/prawn-2.5.0/lib/prawn/text.rb +701 -0
- data/prawn-2.5.0/lib/prawn/transformation_stack.rb +63 -0
- data/prawn-2.5.0/lib/prawn/utilities.rb +34 -0
- data/prawn-2.5.0/lib/prawn/version.rb +6 -0
- data/prawn-2.5.0/lib/prawn/view.rb +116 -0
- data/prawn-2.5.0/lib/prawn.rb +83 -0
- 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
|