prawn 2.3.0 → 2.5.0
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/prawn/document/bounding_box.rb +223 -143
- data/lib/prawn/document/column_box.rb +61 -26
- data/lib/prawn/document/internals.rb +25 -16
- data/lib/prawn/document/span.rb +21 -18
- data/lib/prawn/document.rb +273 -182
- data/lib/prawn/encoding.rb +2 -5
- data/lib/prawn/errors.rb +23 -34
- data/lib/prawn/font.rb +254 -139
- data/lib/prawn/font_metric_cache.rb +18 -16
- data/lib/prawn/fonts/afm.rb +99 -57
- data/lib/prawn/fonts/dfont.rb +7 -1
- data/lib/prawn/fonts/otf.rb +4 -1
- data/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
- data/lib/prawn/fonts/ttc.rb +7 -2
- data/lib/prawn/fonts/ttf.rb +345 -107
- data/lib/prawn/fonts.rb +14 -0
- data/lib/prawn/graphics/blend_mode.rb +25 -28
- data/lib/prawn/graphics/cap_style.rb +9 -12
- data/lib/prawn/graphics/color.rb +75 -50
- data/lib/prawn/graphics/dash.rb +45 -42
- data/lib/prawn/graphics/join_style.rb +18 -12
- data/lib/prawn/graphics/patterns.rb +239 -110
- data/lib/prawn/graphics/transformation.rb +51 -44
- data/lib/prawn/graphics/transparency.rb +16 -40
- data/lib/prawn/graphics.rb +370 -260
- data/lib/prawn/grid.rb +219 -57
- data/lib/prawn/image_handler.rb +27 -10
- data/lib/prawn/images/image.rb +8 -10
- data/lib/prawn/images/jpg.rb +46 -20
- data/lib/prawn/images/png.rb +94 -42
- data/lib/prawn/images.rb +70 -81
- data/lib/prawn/measurement_extensions.rb +39 -8
- data/lib/prawn/measurements.rb +60 -5
- data/lib/prawn/outline.rb +120 -113
- data/lib/prawn/repeater.rb +52 -36
- data/lib/prawn/security/arcfour.rb +4 -4
- data/lib/prawn/security.rb +106 -98
- data/lib/prawn/soft_mask.rb +42 -30
- data/lib/prawn/stamp.rb +38 -42
- data/lib/prawn/text/box.rb +156 -105
- data/lib/prawn/text/formatted/arranger.rb +121 -41
- data/lib/prawn/text/formatted/box.rb +239 -163
- data/lib/prawn/text/formatted/fragment.rb +130 -14
- data/lib/prawn/text/formatted/line_wrap.rb +49 -38
- data/lib/prawn/text/formatted/parser.rb +116 -74
- data/lib/prawn/text/formatted/wrap.rb +25 -26
- data/lib/prawn/text/formatted.rb +75 -0
- data/lib/prawn/text.rb +456 -211
- data/lib/prawn/transformation_stack.rb +29 -10
- data/lib/prawn/utilities.rb +13 -13
- data/lib/prawn/version.rb +2 -1
- data/lib/prawn/view.rb +69 -54
- data/lib/prawn.rb +24 -18
- data.tar.gz.sig +0 -0
- metadata +55 -262
- metadata.gz.sig +3 -4
- data/.yardopts +0 -10
- data/Gemfile +0 -5
- data/Rakefile +0 -54
- data/manual/absolute_position.pdf +0 -0
- data/manual/basic_concepts/adding_pages.rb +0 -26
- data/manual/basic_concepts/basic_concepts.rb +0 -43
- data/manual/basic_concepts/creation.rb +0 -38
- data/manual/basic_concepts/cursor.rb +0 -32
- data/manual/basic_concepts/measurement.rb +0 -24
- data/manual/basic_concepts/origin.rb +0 -37
- data/manual/basic_concepts/other_cursor_helpers.rb +0 -39
- data/manual/basic_concepts/view.rb +0 -48
- data/manual/bounding_box/bounding_box.rb +0 -41
- data/manual/bounding_box/bounds.rb +0 -48
- data/manual/bounding_box/canvas.rb +0 -23
- data/manual/bounding_box/creation.rb +0 -22
- data/manual/bounding_box/indentation.rb +0 -45
- data/manual/bounding_box/nesting.rb +0 -52
- data/manual/bounding_box/russian_boxes.rb +0 -40
- data/manual/bounding_box/stretchy.rb +0 -29
- data/manual/contents.rb +0 -35
- data/manual/cover.rb +0 -43
- data/manual/document_and_page_options/background.rb +0 -25
- data/manual/document_and_page_options/document_and_page_options.rb +0 -34
- data/manual/document_and_page_options/metadata.rb +0 -25
- data/manual/document_and_page_options/page_margins.rb +0 -36
- data/manual/document_and_page_options/page_size.rb +0 -34
- data/manual/document_and_page_options/print_scaling.rb +0 -22
- data/manual/example_helper.rb +0 -8
- data/manual/graphics/blend_mode.rb +0 -52
- data/manual/graphics/circle_and_ellipse.rb +0 -21
- data/manual/graphics/color.rb +0 -22
- data/manual/graphics/common_lines.rb +0 -29
- data/manual/graphics/fill_and_stroke.rb +0 -41
- data/manual/graphics/fill_rules.rb +0 -37
- data/manual/graphics/gradients.rb +0 -43
- data/manual/graphics/graphics.rb +0 -64
- data/manual/graphics/helper.rb +0 -27
- data/manual/graphics/line_width.rb +0 -36
- data/manual/graphics/lines_and_curves.rb +0 -40
- data/manual/graphics/polygon.rb +0 -27
- data/manual/graphics/rectangle.rb +0 -20
- data/manual/graphics/rotate.rb +0 -25
- data/manual/graphics/scale.rb +0 -42
- data/manual/graphics/soft_masks.rb +0 -44
- data/manual/graphics/stroke_cap.rb +0 -30
- data/manual/graphics/stroke_dash.rb +0 -47
- data/manual/graphics/stroke_join.rb +0 -29
- data/manual/graphics/translate.rb +0 -28
- data/manual/graphics/transparency.rb +0 -33
- data/manual/how_to_read_this_manual.rb +0 -39
- data/manual/images/absolute_position.rb +0 -22
- data/manual/images/fit.rb +0 -20
- data/manual/images/horizontal.rb +0 -24
- data/manual/images/images.rb +0 -41
- data/manual/images/plain_image.rb +0 -17
- data/manual/images/scale.rb +0 -21
- data/manual/images/vertical.rb +0 -27
- data/manual/images/width_and_height.rb +0 -24
- data/manual/layout/boxes.rb +0 -26
- data/manual/layout/content.rb +0 -24
- data/manual/layout/layout.rb +0 -27
- data/manual/layout/simple_grid.rb +0 -22
- data/manual/outline/add_subsection_to.rb +0 -60
- data/manual/outline/insert_section_after.rb +0 -46
- data/manual/outline/outline.rb +0 -33
- data/manual/outline/sections_and_pages.rb +0 -66
- data/manual/repeatable_content/alternate_page_numbering.rb +0 -36
- data/manual/repeatable_content/page_numbering.rb +0 -55
- data/manual/repeatable_content/repeatable_content.rb +0 -35
- data/manual/repeatable_content/repeater.rb +0 -54
- data/manual/repeatable_content/stamp.rb +0 -40
- data/manual/security/encryption.rb +0 -28
- data/manual/security/permissions.rb +0 -41
- data/manual/security/security.rb +0 -28
- data/manual/table.rb +0 -16
- data/manual/text/alignment.rb +0 -43
- data/manual/text/color.rb +0 -24
- data/manual/text/column_box.rb +0 -30
- data/manual/text/fallback_fonts.rb +0 -41
- data/manual/text/font.rb +0 -40
- data/manual/text/font_size.rb +0 -44
- data/manual/text/font_style.rb +0 -22
- data/manual/text/formatted_callbacks.rb +0 -65
- data/manual/text/formatted_text.rb +0 -58
- data/manual/text/free_flowing_text.rb +0 -50
- data/manual/text/inline.rb +0 -40
- data/manual/text/kerning_and_character_spacing.rb +0 -38
- data/manual/text/leading.rb +0 -24
- data/manual/text/line_wrapping.rb +0 -60
- data/manual/text/paragraph_indentation.rb +0 -32
- data/manual/text/positioned_text.rb +0 -37
- data/manual/text/registering_families.rb +0 -51
- data/manual/text/rendering_and_color.rb +0 -36
- data/manual/text/right_to_left_text.rb +0 -54
- data/manual/text/rotation.rb +0 -47
- data/manual/text/single_usage.rb +0 -36
- data/manual/text/text.rb +0 -75
- data/manual/text/text_box_excess.rb +0 -35
- data/manual/text/text_box_extensions.rb +0 -48
- data/manual/text/text_box_overflow.rb +0 -49
- data/manual/text/utf8.rb +0 -27
- data/manual/text/win_ansi_charset.rb +0 -62
- data/prawn.gemspec +0 -57
- data/spec/data/curves.pdf +0 -66
- data/spec/extensions/encoding_helpers.rb +0 -11
- data/spec/prawn/document/bounding_box_spec.rb +0 -546
- data/spec/prawn/document/column_box_spec.rb +0 -75
- data/spec/prawn/document/security_spec.rb +0 -176
- data/spec/prawn/document_annotations_spec.rb +0 -76
- data/spec/prawn/document_destinations_spec.rb +0 -15
- data/spec/prawn/document_grid_spec.rb +0 -99
- data/spec/prawn/document_reference_spec.rb +0 -27
- data/spec/prawn/document_span_spec.rb +0 -36
- data/spec/prawn/document_spec.rb +0 -802
- data/spec/prawn/font_metric_cache_spec.rb +0 -54
- data/spec/prawn/font_spec.rb +0 -542
- data/spec/prawn/graphics/blend_mode_spec.rb +0 -63
- data/spec/prawn/graphics/transparency_spec.rb +0 -81
- data/spec/prawn/graphics_spec.rb +0 -837
- data/spec/prawn/graphics_stroke_styles_spec.rb +0 -229
- data/spec/prawn/image_handler_spec.rb +0 -53
- data/spec/prawn/images/jpg_spec.rb +0 -20
- data/spec/prawn/images/png_spec.rb +0 -283
- data/spec/prawn/images_spec.rb +0 -224
- data/spec/prawn/measurements_extensions_spec.rb +0 -24
- data/spec/prawn/outline_spec.rb +0 -412
- data/spec/prawn/repeater_spec.rb +0 -165
- data/spec/prawn/soft_mask_spec.rb +0 -74
- data/spec/prawn/stamp_spec.rb +0 -172
- data/spec/prawn/text/box_spec.rb +0 -1112
- data/spec/prawn/text/formatted/arranger_spec.rb +0 -466
- data/spec/prawn/text/formatted/box_spec.rb +0 -846
- data/spec/prawn/text/formatted/fragment_spec.rb +0 -343
- data/spec/prawn/text/formatted/line_wrap_spec.rb +0 -494
- data/spec/prawn/text/formatted/parser_spec.rb +0 -697
- data/spec/prawn/text_draw_text_spec.rb +0 -149
- data/spec/prawn/text_rendering_mode_spec.rb +0 -48
- data/spec/prawn/text_spacing_spec.rb +0 -95
- data/spec/prawn/text_spec.rb +0 -603
- data/spec/prawn/text_with_inline_formatting_spec.rb +0 -35
- data/spec/prawn/transformation_stack_spec.rb +0 -66
- data/spec/prawn/view_spec.rb +0 -63
- data/spec/prawn_manual_spec.rb +0 -35
- data/spec/spec_helper.rb +0 -48
data/lib/prawn/grid.rb
CHANGED
@@ -1,24 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# grid.rb: Provides a basic grid layout system for Prawn
|
4
|
-
#
|
5
|
-
# Contributed by Andrew O'Brien in March 2009
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
|
9
3
|
module Prawn
|
10
|
-
class Document
|
4
|
+
class Document # rubocop: disable Style/Documentation
|
11
5
|
# @group Experimental API
|
12
6
|
|
13
|
-
# Defines the grid system for a particular document.
|
7
|
+
# Defines the grid system for a particular document. Takes the number of
|
14
8
|
# rows and columns and the width to use for the gutter as the
|
15
9
|
# keys :rows, :columns, :gutter, :row_gutter, :column_gutter
|
16
10
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
|
11
|
+
# @note A completely new grid object is built each time `define_grid`
|
12
|
+
# is called. This means that all subsequent calls to grid() will use
|
13
|
+
# the newly defined Grid object -- grids are not nestable like
|
14
|
+
# bounding boxes are.
|
15
|
+
#
|
16
|
+
# @param options [Hash{Symbol => any}]
|
17
|
+
# @option options :columns [Integer] Number of columns in the grid.
|
18
|
+
# @option options :rows [Integer] Number of rows in the grid.
|
19
|
+
# @option options :gutter [Number] Gutter size. `:row_gutter` and
|
20
|
+
# `:column_gutter` are ignored if specified.
|
21
|
+
# @option options :row_gutter [Number] Row gutter size.
|
22
|
+
# @option options :column_gutter [Number] Column gutter size.
|
23
|
+
# @return [Grid]
|
22
24
|
def define_grid(options = {})
|
23
25
|
@boxes = nil
|
24
26
|
@grid = Grid.new(self, options)
|
@@ -27,25 +29,37 @@ module Prawn
|
|
27
29
|
# A method that can either be used to access a particular grid on the page
|
28
30
|
# or work with the grid system directly.
|
29
31
|
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
32
|
+
# @overload grid
|
33
|
+
# Get current grid.
|
34
|
+
#
|
35
|
+
# @return [Grid]
|
36
|
+
#
|
37
|
+
# @overload grid(row, column)
|
38
|
+
# Get a grid box.
|
33
39
|
#
|
40
|
+
# @param row [Integer]
|
41
|
+
# @param column [Integer]
|
42
|
+
# @return [GridBox]
|
43
|
+
#
|
44
|
+
# @overload grid(box1, box2)
|
45
|
+
# Get a grid multi-box.
|
46
|
+
#
|
47
|
+
# @param box1 [Array(Integer, Integer)] Start box coordinates.
|
48
|
+
# @param box2 [Array(Integer, Integer)] End box coordinates.
|
49
|
+
# @return [MultiBox]
|
34
50
|
def grid(*args)
|
35
51
|
@boxes ||= {}
|
36
52
|
@boxes[args] ||=
|
37
|
-
|
38
|
-
|
39
|
-
|
53
|
+
if args.empty?
|
54
|
+
@grid
|
55
|
+
else
|
56
|
+
g1, g2 = args
|
57
|
+
|
58
|
+
if g1.is_a?(Array) && g2.is_a?(Array) &&
|
59
|
+
g1.length == 2 && g2.length == 2
|
60
|
+
multi_box(single_box(*g1), single_box(*g2))
|
40
61
|
else
|
41
|
-
g1, g2
|
42
|
-
|
43
|
-
if g1.is_a?(Array) && g2.is_a?(Array) &&
|
44
|
-
g1.length == 2 && g2.length == 2
|
45
|
-
multi_box(single_box(*g1), single_box(*g2))
|
46
|
-
else
|
47
|
-
single_box(g1, g2)
|
48
|
-
end
|
62
|
+
single_box(g1, g2)
|
49
63
|
end
|
50
64
|
end
|
51
65
|
end
|
@@ -55,10 +69,41 @@ module Prawn
|
|
55
69
|
#
|
56
70
|
# @group Experimental API
|
57
71
|
class Grid
|
58
|
-
|
59
|
-
|
72
|
+
# @private
|
73
|
+
# @return [Prawn::Document]
|
74
|
+
attr_reader :pdf
|
75
|
+
|
76
|
+
# Number of columns in the grid.
|
77
|
+
# @return [Integer]
|
78
|
+
attr_reader :columns
|
79
|
+
|
80
|
+
# Number of rows in the grid.
|
81
|
+
# @return [Integer]
|
82
|
+
attr_reader :rows
|
83
|
+
|
84
|
+
# Gutter size.
|
85
|
+
# @return [Number]
|
86
|
+
attr_reader :gutter
|
87
|
+
|
88
|
+
# Row gutter size.
|
89
|
+
# @return [Number]
|
90
|
+
attr_reader :row_gutter
|
91
|
+
|
92
|
+
# Column gutter size.
|
93
|
+
# @return [Number]
|
94
|
+
attr_reader :column_gutter
|
95
|
+
|
96
|
+
# @param pdf [Prawn::Document]
|
97
|
+
# @param options [Hash{Symbol => any}]
|
98
|
+
# @option options :columns [Integer] Number of columns in the grid.
|
99
|
+
# @option options :rows [Integer] Number of rows in the grid.
|
100
|
+
# @option options :gutter [Number] Gutter size. `:row_gutter` and
|
101
|
+
# `:column_gutter` are ignored if specified.
|
102
|
+
# @option options :row_gutter [Number] Row gutter size.
|
103
|
+
# @option options :column_gutter [Number] Column gutter size.
|
104
|
+
def initialize(pdf, options = {})
|
60
105
|
valid_options = %i[columns rows gutter row_gutter column_gutter]
|
61
|
-
Prawn.verify_options
|
106
|
+
Prawn.verify_options(valid_options, options)
|
62
107
|
|
63
108
|
@pdf = pdf
|
64
109
|
@columns = options[:columns]
|
@@ -67,16 +112,23 @@ module Prawn
|
|
67
112
|
end
|
68
113
|
|
69
114
|
# Calculates the base width of boxes.
|
115
|
+
#
|
116
|
+
# @return [Float]
|
70
117
|
def column_width
|
71
118
|
@column_width ||= subdivide(pdf.bounds.width, columns, column_gutter)
|
72
119
|
end
|
73
120
|
|
74
121
|
# Calculates the base height of boxes.
|
122
|
+
#
|
123
|
+
# @return [Float]
|
75
124
|
def row_height
|
76
125
|
@row_height ||= subdivide(pdf.bounds.height, rows, row_gutter)
|
77
126
|
end
|
78
127
|
|
79
|
-
# Diagnostic tool to show all of the
|
128
|
+
# Diagnostic tool to show all of the grid boxes.
|
129
|
+
#
|
130
|
+
# @param color [Color]
|
131
|
+
# @return [void]
|
80
132
|
def show_all(color = 'CCCCCC')
|
81
133
|
rows.times do |row|
|
82
134
|
columns.times do |column|
|
@@ -88,17 +140,17 @@ module Prawn
|
|
88
140
|
private
|
89
141
|
|
90
142
|
def subdivide(total, num, gutter)
|
91
|
-
(total
|
143
|
+
(Float(total) - (gutter * Float((num - 1)))) / Float(num)
|
92
144
|
end
|
93
145
|
|
94
146
|
def apply_gutter(options)
|
95
147
|
if options.key?(:gutter)
|
96
|
-
@gutter = options[:gutter]
|
148
|
+
@gutter = Float(options[:gutter])
|
97
149
|
@row_gutter = @gutter
|
98
150
|
@column_gutter = @gutter
|
99
151
|
else
|
100
|
-
@row_gutter = options[:row_gutter]
|
101
|
-
@column_gutter = options[:column_gutter]
|
152
|
+
@row_gutter = Float(options[:row_gutter])
|
153
|
+
@column_gutter = Float(options[:column_gutter])
|
102
154
|
@gutter = 0
|
103
155
|
end
|
104
156
|
end
|
@@ -106,10 +158,11 @@ module Prawn
|
|
106
158
|
|
107
159
|
# A Box is a class that represents a bounded area of a page.
|
108
160
|
# A Grid object has methods that allow easy access to the coordinates of
|
109
|
-
# its corners, which can be plugged into most existing
|
161
|
+
# its corners, which can be plugged into most existing Prawn methods.
|
110
162
|
#
|
111
163
|
# @group Experimental API
|
112
164
|
class GridBox
|
165
|
+
# @private
|
113
166
|
attr_reader :pdf
|
114
167
|
|
115
168
|
def initialize(pdf, rows, columns)
|
@@ -121,82 +174,111 @@ module Prawn
|
|
121
174
|
# Mostly diagnostic method that outputs the name of a box as
|
122
175
|
# col_num, row_num
|
123
176
|
#
|
177
|
+
# @return [String]
|
124
178
|
def name
|
125
179
|
"#{@rows},#{@columns}"
|
126
180
|
end
|
127
181
|
|
128
|
-
#
|
182
|
+
# @private
|
129
183
|
def total_height
|
130
|
-
pdf.bounds.height
|
184
|
+
Float(pdf.bounds.height)
|
131
185
|
end
|
132
186
|
|
133
|
-
# Width of a box
|
187
|
+
# Width of a box.
|
188
|
+
#
|
189
|
+
# @return [Float]
|
134
190
|
def width
|
135
|
-
grid.column_width
|
191
|
+
Float(grid.column_width)
|
136
192
|
end
|
137
193
|
|
138
|
-
# Height of a box
|
194
|
+
# Height of a box.
|
195
|
+
#
|
196
|
+
# @return [Float]
|
139
197
|
def height
|
140
|
-
grid.row_height
|
198
|
+
Float(grid.row_height)
|
141
199
|
end
|
142
200
|
|
143
|
-
# Width of the gutter
|
201
|
+
# Width of the gutter.
|
202
|
+
#
|
203
|
+
# @return [Float]
|
144
204
|
def gutter
|
145
|
-
grid.gutter
|
205
|
+
Float(grid.gutter)
|
146
206
|
end
|
147
207
|
|
148
|
-
# x-coordinate of left side
|
208
|
+
# x-coordinate of left side.
|
209
|
+
#
|
210
|
+
# @return [Float]
|
149
211
|
def left
|
150
|
-
@left ||= (width + grid.column_gutter) * @columns
|
212
|
+
@left ||= (width + grid.column_gutter) * Float(@columns)
|
151
213
|
end
|
152
214
|
|
153
|
-
# x-coordinate of right side
|
215
|
+
# x-coordinate of right side.
|
216
|
+
#
|
217
|
+
# @return [Float]
|
154
218
|
def right
|
155
219
|
@right ||= left + width
|
156
220
|
end
|
157
221
|
|
158
|
-
# y-coordinate of the top
|
222
|
+
# y-coordinate of the top.
|
223
|
+
#
|
224
|
+
# @return [Float]
|
159
225
|
def top
|
160
|
-
@top ||= total_height - ((height + grid.row_gutter) * @rows
|
226
|
+
@top ||= total_height - ((height + grid.row_gutter) * Float(@rows))
|
161
227
|
end
|
162
228
|
|
163
|
-
# y-coordinate of the bottom
|
229
|
+
# y-coordinate of the bottom.
|
230
|
+
#
|
231
|
+
# @return [Float]
|
164
232
|
def bottom
|
165
233
|
@bottom ||= top - height
|
166
234
|
end
|
167
235
|
|
168
|
-
# x,y coordinates of top left corner
|
236
|
+
# x,y coordinates of top left corner.
|
237
|
+
#
|
238
|
+
# @return [Array(Float, Float)]
|
169
239
|
def top_left
|
170
240
|
[left, top]
|
171
241
|
end
|
172
242
|
|
173
|
-
# x,y coordinates of top right corner
|
243
|
+
# x,y coordinates of top right corner.
|
244
|
+
#
|
245
|
+
# @return [Array(Float, Float)]
|
174
246
|
def top_right
|
175
247
|
[right, top]
|
176
248
|
end
|
177
249
|
|
178
|
-
# x,y coordinates of bottom left corner
|
250
|
+
# x,y coordinates of bottom left corner.
|
251
|
+
#
|
252
|
+
# @return [Array(Float, Float)]
|
179
253
|
def bottom_left
|
180
254
|
[left, bottom]
|
181
255
|
end
|
182
256
|
|
183
|
-
# x,y coordinates of bottom right corner
|
257
|
+
# x,y coordinates of bottom right corner.
|
258
|
+
#
|
259
|
+
# @return [Array(Float, Float)]
|
184
260
|
def bottom_right
|
185
261
|
[right, bottom]
|
186
262
|
end
|
187
263
|
|
188
264
|
# Creates a standard bounding box based on the grid box.
|
265
|
+
#
|
266
|
+
# @yield
|
267
|
+
# @return [void]
|
189
268
|
def bounding_box(&blk)
|
190
269
|
pdf.bounding_box(top_left, width: width, height: height, &blk)
|
191
270
|
end
|
192
271
|
|
193
|
-
# Diagnostic method
|
272
|
+
# Drawn the box. Diagnostic method.
|
273
|
+
#
|
274
|
+
# @param grid_color [Color]
|
275
|
+
# @return [void]
|
194
276
|
def show(grid_color = 'CCCCCC')
|
195
277
|
bounding_box do
|
196
278
|
original_stroke_color = pdf.stroke_color
|
197
279
|
|
198
280
|
pdf.stroke_color = grid_color
|
199
|
-
pdf.text
|
281
|
+
pdf.text(name)
|
200
282
|
pdf.stroke_bounds
|
201
283
|
|
202
284
|
pdf.stroke_color = original_stroke_color
|
@@ -213,48 +295,128 @@ module Prawn
|
|
213
295
|
# A MultiBox is specified by 2 Boxes and spans the areas between.
|
214
296
|
#
|
215
297
|
# @group Experimental API
|
216
|
-
class MultiBox
|
298
|
+
class MultiBox
|
217
299
|
def initialize(pdf, box1, box2)
|
218
300
|
@pdf = pdf
|
219
301
|
@boxes = [box1, box2]
|
220
302
|
end
|
221
303
|
|
304
|
+
# @private
|
305
|
+
attr_reader :pdf
|
306
|
+
|
307
|
+
# Mostly diagnostic method that outputs the name of a box.
|
308
|
+
#
|
309
|
+
# @return [String]
|
222
310
|
def name
|
223
311
|
@boxes.map(&:name).join(':')
|
224
312
|
end
|
225
313
|
|
314
|
+
# @private
|
226
315
|
def total_height
|
227
316
|
@boxes[0].total_height
|
228
317
|
end
|
229
318
|
|
319
|
+
# Width of a box.
|
320
|
+
#
|
321
|
+
# @return [Float]
|
230
322
|
def width
|
231
323
|
right_box.right - left_box.left
|
232
324
|
end
|
233
325
|
|
326
|
+
# Height of a box.
|
327
|
+
#
|
328
|
+
# @return [Float]
|
234
329
|
def height
|
235
330
|
top_box.top - bottom_box.bottom
|
236
331
|
end
|
237
332
|
|
333
|
+
# Width of the gutter.
|
334
|
+
#
|
335
|
+
# @return [Float]
|
238
336
|
def gutter
|
239
337
|
@boxes[0].gutter
|
240
338
|
end
|
241
339
|
|
340
|
+
# x-coordinate of left side.
|
341
|
+
#
|
342
|
+
# @return [Float]
|
242
343
|
def left
|
243
344
|
left_box.left
|
244
345
|
end
|
245
346
|
|
347
|
+
# x-coordinate of right side.
|
348
|
+
#
|
349
|
+
# @return [Float]
|
246
350
|
def right
|
247
351
|
right_box.right
|
248
352
|
end
|
249
353
|
|
354
|
+
# y-coordinate of the top.
|
355
|
+
#
|
356
|
+
# @return [Float]
|
250
357
|
def top
|
251
358
|
top_box.top
|
252
359
|
end
|
253
360
|
|
361
|
+
# y-coordinate of the bottom.
|
362
|
+
#
|
363
|
+
# @return [Float]
|
254
364
|
def bottom
|
255
365
|
bottom_box.bottom
|
256
366
|
end
|
257
367
|
|
368
|
+
# x,y coordinates of top left corner.
|
369
|
+
#
|
370
|
+
# @return [Array(Float, Float)]
|
371
|
+
def top_left
|
372
|
+
[left, top]
|
373
|
+
end
|
374
|
+
|
375
|
+
# x,y coordinates of top right corner.
|
376
|
+
#
|
377
|
+
# @return [Array(Float, Float)]
|
378
|
+
def top_right
|
379
|
+
[right, top]
|
380
|
+
end
|
381
|
+
|
382
|
+
# x,y coordinates of bottom left corner.
|
383
|
+
#
|
384
|
+
# @return [Array(Float, Float)]
|
385
|
+
def bottom_left
|
386
|
+
[left, bottom]
|
387
|
+
end
|
388
|
+
|
389
|
+
# x,y coordinates of bottom right corner.
|
390
|
+
#
|
391
|
+
# @return [Array(Float, Float)]
|
392
|
+
def bottom_right
|
393
|
+
[right, bottom]
|
394
|
+
end
|
395
|
+
|
396
|
+
# Creates a standard bounding box based on the grid box.
|
397
|
+
#
|
398
|
+
# @yield
|
399
|
+
# @return [void]
|
400
|
+
def bounding_box(&blk)
|
401
|
+
pdf.bounding_box(top_left, width: width, height: height, &blk)
|
402
|
+
end
|
403
|
+
|
404
|
+
# Drawn the box. Diagnostic method.
|
405
|
+
#
|
406
|
+
# @param grid_color [Color]
|
407
|
+
# @return [void]
|
408
|
+
def show(grid_color = 'CCCCCC')
|
409
|
+
bounding_box do
|
410
|
+
original_stroke_color = pdf.stroke_color
|
411
|
+
|
412
|
+
pdf.stroke_color = grid_color
|
413
|
+
pdf.text(name)
|
414
|
+
pdf.stroke_bounds
|
415
|
+
|
416
|
+
pdf.stroke_color = original_stroke_color
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
258
420
|
private
|
259
421
|
|
260
422
|
def left_box
|
data/lib/prawn/image_handler.rb
CHANGED
@@ -1,39 +1,56 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
#
|
5
|
-
# Contributed by Evan Sharp in November 2013.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
|
9
|
-
module Prawn
|
3
|
+
module Prawn # rubocop: disable Style/Documentation
|
10
4
|
# @group Extension API
|
11
5
|
|
6
|
+
# Image handler.
|
7
|
+
#
|
8
|
+
# @return [ImageHandler]
|
12
9
|
def self.image_handler
|
13
10
|
@image_handler ||= ImageHandler.new
|
14
11
|
end
|
15
12
|
|
13
|
+
# ImageHandler provides a way to register image processors with Prawn.
|
16
14
|
class ImageHandler
|
15
|
+
# @private
|
17
16
|
def initialize
|
18
17
|
@handlers = []
|
19
18
|
end
|
20
19
|
|
20
|
+
# Register an image handler.
|
21
|
+
#
|
22
|
+
# @param handler [Object]
|
23
|
+
# @return [void]
|
21
24
|
def register(handler)
|
22
25
|
@handlers.delete(handler)
|
23
|
-
@handlers.push
|
26
|
+
@handlers.push(handler)
|
24
27
|
end
|
25
28
|
|
29
|
+
# Register an image handler with the highest priority.
|
30
|
+
#
|
31
|
+
# @param handler [Object]
|
32
|
+
# @return [void]
|
26
33
|
def register!(handler)
|
27
34
|
@handlers.delete(handler)
|
28
|
-
@handlers.unshift
|
35
|
+
@handlers.unshift(handler)
|
29
36
|
end
|
30
37
|
|
38
|
+
# Unregister an image handler.
|
39
|
+
#
|
40
|
+
# @param handler [Object]
|
41
|
+
# @return [void]
|
31
42
|
def unregister(handler)
|
32
43
|
@handlers.reject! { |h| h == handler }
|
33
44
|
end
|
34
45
|
|
46
|
+
# Find an image handler for an image.
|
47
|
+
#
|
48
|
+
# @param image_blob [String]
|
49
|
+
# @return [Object]
|
50
|
+
# @raise [Prawn::Errors::UnsupportedImageType] If no image handler were
|
51
|
+
# found for the image.
|
35
52
|
def find(image_blob)
|
36
|
-
handler = @handlers.find { |h| h.can_render?
|
53
|
+
handler = @handlers.find { |h| h.can_render?(image_blob) }
|
37
54
|
|
38
55
|
return handler if handler
|
39
56
|
|
data/lib/prawn/images/image.rb
CHANGED
@@ -1,28 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# image.rb : Base class for image info objects
|
4
|
-
#
|
5
|
-
# Copyright September 2011, Brad Ediger. All rights reserved.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
|
9
3
|
require 'digest/sha1'
|
10
4
|
|
11
5
|
module Prawn
|
12
6
|
module Images
|
7
|
+
# Base class for image info objects
|
8
|
+
# @abstract
|
13
9
|
class Image
|
14
10
|
# @group Extension API
|
15
11
|
|
12
|
+
# Calculate the final image dimensions from provided options.
|
13
|
+
# @private
|
16
14
|
def calc_image_dimensions(options)
|
17
15
|
w = options[:width] || width
|
18
16
|
h = options[:height] || height
|
19
17
|
|
20
18
|
if options[:width] && !options[:height]
|
21
|
-
wp = w / width
|
19
|
+
wp = w / Float(width)
|
22
20
|
w = width * wp
|
23
21
|
h = height * wp
|
24
22
|
elsif options[:height] && !options[:width]
|
25
|
-
hp = h / height
|
23
|
+
hp = h / Float(height)
|
26
24
|
w = width * hp
|
27
25
|
h = height * hp
|
28
26
|
elsif options[:scale]
|
@@ -30,8 +28,8 @@ module Prawn
|
|
30
28
|
h = height * options[:scale]
|
31
29
|
elsif options[:fit]
|
32
30
|
bw, bh = options[:fit]
|
33
|
-
bp = bw / bh
|
34
|
-
ip = width / height
|
31
|
+
bp = bw / Float(bh)
|
32
|
+
ip = width / Float(height)
|
35
33
|
if ip > bp
|
36
34
|
w = bw
|
37
35
|
h = bw / ip
|
data/lib/prawn/images/jpg.rb
CHANGED
@@ -1,40 +1,62 @@
|
|
1
1
|
# encoding: ASCII-8BIT
|
2
|
-
|
3
2
|
# frozen_string_literal: true
|
4
3
|
|
5
|
-
# jpg.rb : Extracts the data from a JPG that is needed for embedding
|
6
|
-
#
|
7
|
-
# Copyright April 2008, James Healy. All Rights Reserved.
|
8
|
-
#
|
9
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
10
|
-
|
11
4
|
require 'stringio'
|
12
5
|
|
13
6
|
module Prawn
|
14
|
-
module Images
|
15
|
-
# A convenience class that wraps the logic for extracting the parts
|
16
|
-
#
|
17
|
-
#
|
7
|
+
module Images # rubocop: disable Style/Documentation
|
8
|
+
# A convenience class that wraps the logic for extracting the parts of a JPG
|
9
|
+
# image that we need to embed them in a PDF.
|
18
10
|
class JPG < Image
|
11
|
+
# Signals an issue with the image format. The image is probably corrupted
|
12
|
+
# if you're getting this.
|
13
|
+
class FormatError < StandardError; end
|
14
|
+
|
19
15
|
# @group Extension API
|
20
16
|
|
21
|
-
|
22
|
-
|
17
|
+
# Image width in pixels.
|
18
|
+
# @return [Integer]
|
19
|
+
attr_reader :width
|
20
|
+
|
21
|
+
# Image height in pixels.
|
22
|
+
# @return [Integer]
|
23
|
+
attr_reader :height
|
24
|
+
|
25
|
+
# Sample Precision in bits.
|
26
|
+
# @return [Integer]
|
27
|
+
attr_reader :bits
|
28
|
+
|
29
|
+
# Number of image components (channels).
|
30
|
+
# @return [Integer]
|
31
|
+
attr_reader :channels
|
23
32
|
|
33
|
+
# Scaled width of the image in PDF points.
|
34
|
+
# @return [Number]
|
35
|
+
attr_accessor :scaled_width
|
36
|
+
|
37
|
+
# Scaled height of the image in PDF points.
|
38
|
+
# @return [Number]
|
39
|
+
attr_accessor :scaled_height
|
40
|
+
|
41
|
+
# @private
|
24
42
|
JPEG_SOF_BLOCKS = [
|
25
43
|
0xC0, 0xC1, 0xC2, 0xC3, 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE,
|
26
|
-
0xCF
|
44
|
+
0xCF,
|
27
45
|
].freeze
|
28
46
|
|
47
|
+
# Can this image handler process this image?
|
48
|
+
#
|
49
|
+
# @param image_blob [String]
|
50
|
+
# @return [Boolean]
|
29
51
|
def self.can_render?(image_blob)
|
30
52
|
image_blob[0, 3].unpack('C*') == [255, 216, 255]
|
31
53
|
end
|
32
54
|
|
33
|
-
# Process a new JPG image
|
34
|
-
#
|
35
|
-
# <tt>:data</tt>:: A binary string of JPEG data
|
55
|
+
# Process a new JPG image.
|
36
56
|
#
|
57
|
+
# @param data [String] A binary string of JPEG data.
|
37
58
|
def initialize(data)
|
59
|
+
super()
|
38
60
|
@data = data
|
39
61
|
d = StringIO.new(@data)
|
40
62
|
d.binmode
|
@@ -43,7 +65,7 @@ module Prawn
|
|
43
65
|
d.seek(2) # Skip the first two bytes of JPEG identifier.
|
44
66
|
loop do
|
45
67
|
marker, code, length = d.read(4).unpack('CCn')
|
46
|
-
raise 'JPEG marker not found!' if marker != c_marker
|
68
|
+
raise FormatError, 'JPEG marker not found!' if marker != c_marker
|
47
69
|
|
48
70
|
if JPEG_SOF_BLOCKS.include?(code)
|
49
71
|
@bits, @height, @width, @channels = d.read(6).unpack('CnnC')
|
@@ -54,9 +76,11 @@ module Prawn
|
|
54
76
|
end
|
55
77
|
end
|
56
78
|
|
57
|
-
# Build a PDF object representing this image in
|
79
|
+
# Build a PDF object representing this image in `document`, and return
|
58
80
|
# a Reference to it.
|
59
81
|
#
|
82
|
+
# @param document [Prawn::Document]
|
83
|
+
# @return [PDF::Core::Reference]
|
60
84
|
def build_pdf_object(document)
|
61
85
|
color_space =
|
62
86
|
case channels
|
@@ -76,7 +100,7 @@ module Prawn
|
|
76
100
|
ColorSpace: color_space,
|
77
101
|
BitsPerComponent: bits,
|
78
102
|
Width: width,
|
79
|
-
Height: height
|
103
|
+
Height: height,
|
80
104
|
)
|
81
105
|
|
82
106
|
# add extra decode params for CMYK images. By swapping the
|
@@ -91,5 +115,7 @@ module Prawn
|
|
91
115
|
obj
|
92
116
|
end
|
93
117
|
end
|
118
|
+
|
119
|
+
Prawn.image_handler.register(Prawn::Images::JPG)
|
94
120
|
end
|
95
121
|
end
|