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.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/prawn/document/bounding_box.rb +223 -143
  4. data/lib/prawn/document/column_box.rb +61 -26
  5. data/lib/prawn/document/internals.rb +25 -16
  6. data/lib/prawn/document/span.rb +21 -18
  7. data/lib/prawn/document.rb +273 -182
  8. data/lib/prawn/encoding.rb +2 -5
  9. data/lib/prawn/errors.rb +23 -34
  10. data/lib/prawn/font.rb +254 -139
  11. data/lib/prawn/font_metric_cache.rb +18 -16
  12. data/lib/prawn/fonts/afm.rb +99 -57
  13. data/lib/prawn/fonts/dfont.rb +7 -1
  14. data/lib/prawn/fonts/otf.rb +4 -1
  15. data/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
  16. data/lib/prawn/fonts/ttc.rb +7 -2
  17. data/lib/prawn/fonts/ttf.rb +345 -107
  18. data/lib/prawn/fonts.rb +14 -0
  19. data/lib/prawn/graphics/blend_mode.rb +25 -28
  20. data/lib/prawn/graphics/cap_style.rb +9 -12
  21. data/lib/prawn/graphics/color.rb +75 -50
  22. data/lib/prawn/graphics/dash.rb +45 -42
  23. data/lib/prawn/graphics/join_style.rb +18 -12
  24. data/lib/prawn/graphics/patterns.rb +239 -110
  25. data/lib/prawn/graphics/transformation.rb +51 -44
  26. data/lib/prawn/graphics/transparency.rb +16 -40
  27. data/lib/prawn/graphics.rb +370 -260
  28. data/lib/prawn/grid.rb +219 -57
  29. data/lib/prawn/image_handler.rb +27 -10
  30. data/lib/prawn/images/image.rb +8 -10
  31. data/lib/prawn/images/jpg.rb +46 -20
  32. data/lib/prawn/images/png.rb +94 -42
  33. data/lib/prawn/images.rb +70 -81
  34. data/lib/prawn/measurement_extensions.rb +39 -8
  35. data/lib/prawn/measurements.rb +60 -5
  36. data/lib/prawn/outline.rb +120 -113
  37. data/lib/prawn/repeater.rb +52 -36
  38. data/lib/prawn/security/arcfour.rb +4 -4
  39. data/lib/prawn/security.rb +106 -98
  40. data/lib/prawn/soft_mask.rb +42 -30
  41. data/lib/prawn/stamp.rb +38 -42
  42. data/lib/prawn/text/box.rb +156 -105
  43. data/lib/prawn/text/formatted/arranger.rb +121 -41
  44. data/lib/prawn/text/formatted/box.rb +239 -163
  45. data/lib/prawn/text/formatted/fragment.rb +130 -14
  46. data/lib/prawn/text/formatted/line_wrap.rb +49 -38
  47. data/lib/prawn/text/formatted/parser.rb +116 -74
  48. data/lib/prawn/text/formatted/wrap.rb +25 -26
  49. data/lib/prawn/text/formatted.rb +75 -0
  50. data/lib/prawn/text.rb +456 -211
  51. data/lib/prawn/transformation_stack.rb +29 -10
  52. data/lib/prawn/utilities.rb +13 -13
  53. data/lib/prawn/version.rb +2 -1
  54. data/lib/prawn/view.rb +69 -54
  55. data/lib/prawn.rb +24 -18
  56. data.tar.gz.sig +0 -0
  57. metadata +55 -262
  58. metadata.gz.sig +3 -4
  59. data/.yardopts +0 -10
  60. data/Gemfile +0 -5
  61. data/Rakefile +0 -54
  62. data/manual/absolute_position.pdf +0 -0
  63. data/manual/basic_concepts/adding_pages.rb +0 -26
  64. data/manual/basic_concepts/basic_concepts.rb +0 -43
  65. data/manual/basic_concepts/creation.rb +0 -38
  66. data/manual/basic_concepts/cursor.rb +0 -32
  67. data/manual/basic_concepts/measurement.rb +0 -24
  68. data/manual/basic_concepts/origin.rb +0 -37
  69. data/manual/basic_concepts/other_cursor_helpers.rb +0 -39
  70. data/manual/basic_concepts/view.rb +0 -48
  71. data/manual/bounding_box/bounding_box.rb +0 -41
  72. data/manual/bounding_box/bounds.rb +0 -48
  73. data/manual/bounding_box/canvas.rb +0 -23
  74. data/manual/bounding_box/creation.rb +0 -22
  75. data/manual/bounding_box/indentation.rb +0 -45
  76. data/manual/bounding_box/nesting.rb +0 -52
  77. data/manual/bounding_box/russian_boxes.rb +0 -40
  78. data/manual/bounding_box/stretchy.rb +0 -29
  79. data/manual/contents.rb +0 -35
  80. data/manual/cover.rb +0 -43
  81. data/manual/document_and_page_options/background.rb +0 -25
  82. data/manual/document_and_page_options/document_and_page_options.rb +0 -34
  83. data/manual/document_and_page_options/metadata.rb +0 -25
  84. data/manual/document_and_page_options/page_margins.rb +0 -36
  85. data/manual/document_and_page_options/page_size.rb +0 -34
  86. data/manual/document_and_page_options/print_scaling.rb +0 -22
  87. data/manual/example_helper.rb +0 -8
  88. data/manual/graphics/blend_mode.rb +0 -52
  89. data/manual/graphics/circle_and_ellipse.rb +0 -21
  90. data/manual/graphics/color.rb +0 -22
  91. data/manual/graphics/common_lines.rb +0 -29
  92. data/manual/graphics/fill_and_stroke.rb +0 -41
  93. data/manual/graphics/fill_rules.rb +0 -37
  94. data/manual/graphics/gradients.rb +0 -43
  95. data/manual/graphics/graphics.rb +0 -64
  96. data/manual/graphics/helper.rb +0 -27
  97. data/manual/graphics/line_width.rb +0 -36
  98. data/manual/graphics/lines_and_curves.rb +0 -40
  99. data/manual/graphics/polygon.rb +0 -27
  100. data/manual/graphics/rectangle.rb +0 -20
  101. data/manual/graphics/rotate.rb +0 -25
  102. data/manual/graphics/scale.rb +0 -42
  103. data/manual/graphics/soft_masks.rb +0 -44
  104. data/manual/graphics/stroke_cap.rb +0 -30
  105. data/manual/graphics/stroke_dash.rb +0 -47
  106. data/manual/graphics/stroke_join.rb +0 -29
  107. data/manual/graphics/translate.rb +0 -28
  108. data/manual/graphics/transparency.rb +0 -33
  109. data/manual/how_to_read_this_manual.rb +0 -39
  110. data/manual/images/absolute_position.rb +0 -22
  111. data/manual/images/fit.rb +0 -20
  112. data/manual/images/horizontal.rb +0 -24
  113. data/manual/images/images.rb +0 -41
  114. data/manual/images/plain_image.rb +0 -17
  115. data/manual/images/scale.rb +0 -21
  116. data/manual/images/vertical.rb +0 -27
  117. data/manual/images/width_and_height.rb +0 -24
  118. data/manual/layout/boxes.rb +0 -26
  119. data/manual/layout/content.rb +0 -24
  120. data/manual/layout/layout.rb +0 -27
  121. data/manual/layout/simple_grid.rb +0 -22
  122. data/manual/outline/add_subsection_to.rb +0 -60
  123. data/manual/outline/insert_section_after.rb +0 -46
  124. data/manual/outline/outline.rb +0 -33
  125. data/manual/outline/sections_and_pages.rb +0 -66
  126. data/manual/repeatable_content/alternate_page_numbering.rb +0 -36
  127. data/manual/repeatable_content/page_numbering.rb +0 -55
  128. data/manual/repeatable_content/repeatable_content.rb +0 -35
  129. data/manual/repeatable_content/repeater.rb +0 -54
  130. data/manual/repeatable_content/stamp.rb +0 -40
  131. data/manual/security/encryption.rb +0 -28
  132. data/manual/security/permissions.rb +0 -41
  133. data/manual/security/security.rb +0 -28
  134. data/manual/table.rb +0 -16
  135. data/manual/text/alignment.rb +0 -43
  136. data/manual/text/color.rb +0 -24
  137. data/manual/text/column_box.rb +0 -30
  138. data/manual/text/fallback_fonts.rb +0 -41
  139. data/manual/text/font.rb +0 -40
  140. data/manual/text/font_size.rb +0 -44
  141. data/manual/text/font_style.rb +0 -22
  142. data/manual/text/formatted_callbacks.rb +0 -65
  143. data/manual/text/formatted_text.rb +0 -58
  144. data/manual/text/free_flowing_text.rb +0 -50
  145. data/manual/text/inline.rb +0 -40
  146. data/manual/text/kerning_and_character_spacing.rb +0 -38
  147. data/manual/text/leading.rb +0 -24
  148. data/manual/text/line_wrapping.rb +0 -60
  149. data/manual/text/paragraph_indentation.rb +0 -32
  150. data/manual/text/positioned_text.rb +0 -37
  151. data/manual/text/registering_families.rb +0 -51
  152. data/manual/text/rendering_and_color.rb +0 -36
  153. data/manual/text/right_to_left_text.rb +0 -54
  154. data/manual/text/rotation.rb +0 -47
  155. data/manual/text/single_usage.rb +0 -36
  156. data/manual/text/text.rb +0 -75
  157. data/manual/text/text_box_excess.rb +0 -35
  158. data/manual/text/text_box_extensions.rb +0 -48
  159. data/manual/text/text_box_overflow.rb +0 -49
  160. data/manual/text/utf8.rb +0 -27
  161. data/manual/text/win_ansi_charset.rb +0 -62
  162. data/prawn.gemspec +0 -57
  163. data/spec/data/curves.pdf +0 -66
  164. data/spec/extensions/encoding_helpers.rb +0 -11
  165. data/spec/prawn/document/bounding_box_spec.rb +0 -546
  166. data/spec/prawn/document/column_box_spec.rb +0 -75
  167. data/spec/prawn/document/security_spec.rb +0 -176
  168. data/spec/prawn/document_annotations_spec.rb +0 -76
  169. data/spec/prawn/document_destinations_spec.rb +0 -15
  170. data/spec/prawn/document_grid_spec.rb +0 -99
  171. data/spec/prawn/document_reference_spec.rb +0 -27
  172. data/spec/prawn/document_span_spec.rb +0 -36
  173. data/spec/prawn/document_spec.rb +0 -802
  174. data/spec/prawn/font_metric_cache_spec.rb +0 -54
  175. data/spec/prawn/font_spec.rb +0 -542
  176. data/spec/prawn/graphics/blend_mode_spec.rb +0 -63
  177. data/spec/prawn/graphics/transparency_spec.rb +0 -81
  178. data/spec/prawn/graphics_spec.rb +0 -837
  179. data/spec/prawn/graphics_stroke_styles_spec.rb +0 -229
  180. data/spec/prawn/image_handler_spec.rb +0 -53
  181. data/spec/prawn/images/jpg_spec.rb +0 -20
  182. data/spec/prawn/images/png_spec.rb +0 -283
  183. data/spec/prawn/images_spec.rb +0 -224
  184. data/spec/prawn/measurements_extensions_spec.rb +0 -24
  185. data/spec/prawn/outline_spec.rb +0 -412
  186. data/spec/prawn/repeater_spec.rb +0 -165
  187. data/spec/prawn/soft_mask_spec.rb +0 -74
  188. data/spec/prawn/stamp_spec.rb +0 -172
  189. data/spec/prawn/text/box_spec.rb +0 -1112
  190. data/spec/prawn/text/formatted/arranger_spec.rb +0 -466
  191. data/spec/prawn/text/formatted/box_spec.rb +0 -846
  192. data/spec/prawn/text/formatted/fragment_spec.rb +0 -343
  193. data/spec/prawn/text/formatted/line_wrap_spec.rb +0 -494
  194. data/spec/prawn/text/formatted/parser_spec.rb +0 -697
  195. data/spec/prawn/text_draw_text_spec.rb +0 -149
  196. data/spec/prawn/text_rendering_mode_spec.rb +0 -48
  197. data/spec/prawn/text_spacing_spec.rb +0 -95
  198. data/spec/prawn/text_spec.rb +0 -603
  199. data/spec/prawn/text_with_inline_formatting_spec.rb +0 -35
  200. data/spec/prawn/transformation_stack_spec.rb +0 -66
  201. data/spec/prawn/view_spec.rb +0 -63
  202. data/spec/prawn_manual_spec.rb +0 -35
  203. 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. Takes the number of
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
- # Note that a completely new grid object is built each time define_grid()
18
- # is called. This means that all subsequent calls to grid() will use
19
- # the newly defined Grid object -- grids are not nestable like
20
- # bounding boxes are.
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
- # @pdf.grid # Get the Grid directly
31
- # @pdf.grid([0,1]) # Get the GridBox at [0,1]
32
- # @pdf.grid([0,1], [1,2]) # Get a multi-box spanning from [0,1] to [1,2]
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
- begin
38
- if args.empty?
39
- @grid
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 = args
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
- attr_reader :pdf, :columns, :rows, :gutter, :row_gutter, :column_gutter
59
- def initialize(pdf, options = {}) # :nodoc:
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 valid_options, 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 grids. Defaults to gray.
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.to_f - (gutter * (num - 1).to_f)) / num.to_f
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].to_f
148
+ @gutter = Float(options[:gutter])
97
149
  @row_gutter = @gutter
98
150
  @column_gutter = @gutter
99
151
  else
100
- @row_gutter = options[:row_gutter].to_f
101
- @column_gutter = options[:column_gutter].to_f
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 prawnmethods.
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
- # :nodoc
182
+ # @private
129
183
  def total_height
130
- pdf.bounds.height.to_f
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.to_f
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.to_f
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.to_f
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.to_f
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.to_f)
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 name
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 < GridBox
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
@@ -1,39 +1,56 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # ImageHandler provides a way to register image processors with Prawn
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 handler
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 handler
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? image_blob }
53
+ handler = @handlers.find { |h| h.can_render?(image_blob) }
37
54
 
38
55
  return handler if handler
39
56
 
@@ -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.to_f
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.to_f
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.to_f
34
- ip = width / height.to_f
31
+ bp = bw / Float(bh)
32
+ ip = width / Float(height)
35
33
  if ip > bp
36
34
  w = bw
37
35
  h = bw / ip
@@ -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
- # of a JPG image that we need to embed them in a PDF
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
- attr_reader :width, :height, :bits, :channels
22
- attr_accessor :scaled_width, :scaled_height
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 +document+, and return
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