prawn 1.1.0 → 2.4.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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.yardopts +1 -0
- data/GPLv2 +20 -21
- data/Gemfile +3 -9
- data/Rakefile +9 -40
- data/lib/prawn/document/bounding_box.rb +54 -40
- data/lib/prawn/document/column_box.rb +8 -10
- data/lib/prawn/document/internals.rb +39 -146
- data/lib/prawn/document/span.rb +23 -17
- data/lib/prawn/document.rb +217 -182
- data/lib/prawn/encoding.rb +69 -101
- data/lib/prawn/errors.rb +47 -43
- data/lib/prawn/font.rb +124 -104
- data/lib/prawn/font_metric_cache.rb +23 -21
- data/lib/prawn/fonts/afm.rb +292 -0
- data/lib/prawn/{font → fonts}/dfont.rb +5 -12
- data/lib/prawn/fonts/otf.rb +11 -0
- data/lib/prawn/fonts/ttc.rb +36 -0
- data/lib/prawn/{font → fonts}/ttf.rb +140 -88
- data/lib/prawn/graphics/blend_mode.rb +65 -0
- data/lib/prawn/graphics/cap_style.rb +5 -5
- data/lib/prawn/graphics/color.rb +46 -44
- data/lib/prawn/graphics/dash.rb +27 -11
- data/lib/prawn/graphics/join_style.rb +11 -6
- data/lib/prawn/graphics/patterns.rb +220 -78
- data/lib/prawn/graphics/transformation.rb +20 -12
- data/lib/prawn/graphics/transparency.rb +20 -18
- data/lib/prawn/graphics.rb +153 -115
- data/lib/prawn/grid.rb +93 -50
- data/lib/prawn/image_handler.rb +4 -4
- data/lib/prawn/images/image.rb +3 -2
- data/lib/prawn/images/jpg.rb +31 -24
- data/lib/prawn/images/png.rb +101 -68
- data/lib/prawn/images.rb +64 -56
- data/lib/prawn/measurement_extensions.rb +10 -9
- data/lib/prawn/measurements.rb +20 -23
- data/lib/prawn/outline.rb +96 -75
- data/lib/prawn/repeater.rb +16 -16
- data/lib/prawn/security/arcfour.rb +2 -2
- data/lib/prawn/security.rb +100 -85
- data/lib/prawn/soft_mask.rb +37 -38
- data/lib/prawn/stamp.rb +28 -13
- data/lib/prawn/text/box.rb +24 -29
- data/lib/prawn/text/formatted/arranger.rb +108 -63
- data/lib/prawn/text/formatted/box.rb +187 -124
- data/lib/prawn/text/formatted/fragment.rb +24 -20
- data/lib/prawn/text/formatted/line_wrap.rb +133 -73
- data/lib/prawn/text/formatted/parser.rb +147 -127
- data/lib/prawn/text/formatted/wrap.rb +48 -35
- data/lib/prawn/text/formatted.rb +5 -5
- data/lib/prawn/text.rb +103 -68
- data/lib/prawn/transformation_stack.rb +44 -0
- data/lib/prawn/utilities.rb +10 -22
- data/lib/prawn/version.rb +5 -0
- data/lib/prawn/view.rb +101 -0
- data/lib/prawn.rb +39 -54
- data/manual/basic_concepts/adding_pages.rb +6 -7
- data/manual/basic_concepts/basic_concepts.rb +34 -25
- data/manual/basic_concepts/creation.rb +10 -11
- data/manual/basic_concepts/cursor.rb +4 -5
- data/manual/basic_concepts/measurement.rb +8 -9
- data/manual/basic_concepts/origin.rb +5 -6
- data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
- data/manual/basic_concepts/view.rb +48 -0
- data/manual/bounding_box/bounding_box.rb +30 -28
- data/manual/bounding_box/bounds.rb +12 -13
- data/manual/bounding_box/canvas.rb +7 -8
- data/manual/bounding_box/creation.rb +6 -7
- data/manual/bounding_box/indentation.rb +14 -15
- data/manual/bounding_box/nesting.rb +25 -18
- data/manual/bounding_box/russian_boxes.rb +18 -18
- data/manual/bounding_box/stretchy.rb +12 -14
- data/manual/contents.rb +28 -22
- data/manual/cover.rb +33 -32
- data/manual/document_and_page_options/background.rb +15 -13
- data/manual/document_and_page_options/document_and_page_options.rb +24 -22
- data/manual/document_and_page_options/metadata.rb +20 -18
- data/manual/document_and_page_options/page_margins.rb +18 -20
- data/manual/document_and_page_options/page_size.rb +13 -13
- data/manual/document_and_page_options/print_scaling.rb +18 -15
- data/manual/example_helper.rb +5 -4
- data/manual/graphics/blend_mode.rb +52 -0
- data/manual/graphics/circle_and_ellipse.rb +4 -5
- data/manual/graphics/color.rb +7 -9
- data/manual/graphics/common_lines.rb +7 -8
- data/manual/graphics/fill_and_stroke.rb +5 -6
- data/manual/graphics/fill_rules.rb +12 -11
- data/manual/graphics/gradients.rb +27 -21
- data/manual/graphics/graphics.rb +46 -40
- data/manual/graphics/helper.rb +19 -9
- data/manual/graphics/line_width.rb +8 -7
- data/manual/graphics/lines_and_curves.rb +8 -9
- data/manual/graphics/polygon.rb +6 -8
- data/manual/graphics/rectangle.rb +4 -5
- data/manual/graphics/rotate.rb +6 -9
- data/manual/graphics/scale.rb +14 -13
- data/manual/graphics/soft_masks.rb +4 -6
- data/manual/graphics/stroke_cap.rb +7 -8
- data/manual/graphics/stroke_dash.rb +15 -16
- data/manual/graphics/stroke_join.rb +6 -7
- data/manual/graphics/translate.rb +10 -10
- data/manual/graphics/transparency.rb +7 -9
- data/manual/how_to_read_this_manual.rb +8 -9
- data/manual/images/absolute_position.rb +6 -7
- data/manual/images/fit.rb +7 -8
- data/manual/images/horizontal.rb +10 -11
- data/manual/images/images.rb +28 -27
- data/manual/images/plain_image.rb +5 -6
- data/manual/images/scale.rb +9 -10
- data/manual/images/vertical.rb +16 -14
- data/manual/images/width_and_height.rb +10 -11
- data/manual/layout/boxes.rb +10 -11
- data/manual/layout/content.rb +9 -10
- data/manual/layout/layout.rb +17 -18
- data/manual/layout/simple_grid.rb +6 -7
- data/manual/outline/add_subsection_to.rb +20 -21
- data/manual/outline/insert_section_after.rb +15 -16
- data/manual/outline/outline.rb +22 -21
- data/manual/outline/sections_and_pages.rb +17 -18
- data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
- data/manual/repeatable_content/page_numbering.rb +17 -16
- data/manual/repeatable_content/repeatable_content.rb +27 -23
- data/manual/repeatable_content/repeater.rb +15 -16
- data/manual/repeatable_content/stamp.rb +14 -15
- data/manual/security/encryption.rb +8 -11
- data/manual/security/permissions.rb +20 -15
- data/manual/security/security.rb +18 -18
- data/manual/table.rb +16 -0
- data/manual/text/alignment.rb +16 -17
- data/manual/text/color.rb +12 -12
- data/manual/text/column_box.rb +9 -11
- data/manual/text/fallback_fonts.rb +25 -21
- data/manual/text/font.rb +11 -12
- data/manual/text/font_size.rb +13 -14
- data/manual/text/font_style.rb +10 -8
- data/manual/text/formatted_callbacks.rb +33 -23
- data/manual/text/formatted_text.rb +36 -25
- data/manual/text/free_flowing_text.rb +22 -23
- data/manual/text/inline.rb +18 -19
- data/manual/text/kerning_and_character_spacing.rb +14 -15
- data/manual/text/leading.rb +7 -8
- data/manual/text/line_wrapping.rb +37 -18
- data/manual/text/paragraph_indentation.rb +15 -10
- data/manual/text/positioned_text.rb +16 -17
- data/manual/text/registering_families.rb +27 -24
- data/manual/text/rendering_and_color.rb +9 -10
- data/manual/text/right_to_left_text.rb +30 -19
- data/manual/text/rotation.rb +33 -24
- data/manual/text/single_usage.rb +8 -9
- data/manual/text/text.rb +56 -54
- data/manual/text/text_box_excess.rb +20 -17
- data/manual/text/text_box_extensions.rb +18 -15
- data/manual/text/text_box_overflow.rb +24 -17
- data/manual/text/utf8.rb +12 -13
- data/manual/text/win_ansi_charset.rb +28 -25
- data/prawn.gemspec +45 -50
- data/spec/extensions/encoding_helpers.rb +3 -3
- data/spec/prawn/document/bounding_box_spec.rb +550 -0
- data/spec/prawn/document/column_box_spec.rb +75 -0
- data/spec/prawn/document/security_spec.rb +176 -0
- data/spec/prawn/document_annotations_spec.rb +76 -0
- data/spec/prawn/document_destinations_spec.rb +15 -0
- data/spec/prawn/document_grid_spec.rb +99 -0
- data/spec/prawn/document_reference_spec.rb +27 -0
- data/spec/prawn/document_span_spec.rb +44 -0
- data/spec/prawn/document_spec.rb +805 -0
- data/spec/prawn/font_metric_cache_spec.rb +54 -0
- data/spec/prawn/font_spec.rb +544 -0
- data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
- data/spec/prawn/graphics/transparency_spec.rb +81 -0
- data/spec/prawn/graphics_spec.rb +872 -0
- data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
- data/spec/prawn/image_handler_spec.rb +53 -0
- data/spec/prawn/images/jpg_spec.rb +20 -0
- data/spec/prawn/images/png_spec.rb +283 -0
- data/spec/prawn/images_spec.rb +229 -0
- data/spec/prawn/measurements_extensions_spec.rb +24 -0
- data/spec/prawn/outline_spec.rb +512 -0
- data/spec/prawn/repeater_spec.rb +166 -0
- data/spec/prawn/soft_mask_spec.rb +74 -0
- data/spec/prawn/stamp_spec.rb +173 -0
- data/spec/prawn/text/box_spec.rb +1110 -0
- data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
- data/spec/prawn/text/formatted/box_spec.rb +849 -0
- data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
- data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
- data/spec/prawn/text/formatted/parser_spec.rb +697 -0
- data/spec/prawn/text_draw_text_spec.rb +150 -0
- data/spec/prawn/text_rendering_mode_spec.rb +48 -0
- data/spec/prawn/text_spacing_spec.rb +95 -0
- data/spec/prawn/text_spec.rb +603 -0
- data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
- data/spec/prawn/transformation_stack_spec.rb +66 -0
- data/spec/prawn/view_spec.rb +63 -0
- data/spec/prawn_manual_spec.rb +35 -0
- data/spec/spec_helper.rb +19 -25
- data.tar.gz.sig +0 -0
- metadata +113 -276
- metadata.gz.sig +0 -0
- data/data/encodings/win_ansi.txt +0 -29
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.color +0 -0
- data/data/images/16bit.png +0 -0
- data/data/images/arrow.png +0 -0
- data/data/images/arrow2.png +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.color +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/dice_interlaced.png +0 -0
- data/data/images/fractal.jpg +0 -0
- data/data/images/indexed_color.dat +0 -0
- data/data/images/indexed_color.png +0 -0
- data/data/images/letterhead.jpg +0 -0
- data/data/images/license.md +0 -8
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.color +0 -0
- data/data/images/page_white_text.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/prawn.png +0 -0
- data/data/images/ruport.png +0 -0
- data/data/images/ruport_data.dat +0 -0
- data/data/images/ruport_transparent.png +0 -0
- data/data/images/ruport_type0.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/images/tru256.bmp +0 -0
- data/data/images/web-links.dat +0 -1
- data/data/images/web-links.png +0 -0
- data/data/pdfs/complex_template.pdf +0 -0
- data/data/pdfs/contains_ttf_font.pdf +0 -0
- data/data/pdfs/encrypted.pdf +0 -0
- data/data/pdfs/form.pdf +1 -819
- data/data/pdfs/hexagon.pdf +0 -61
- data/data/pdfs/indirect_reference.pdf +0 -86
- data/data/pdfs/multipage_template.pdf +0 -127
- data/data/pdfs/nested_pages.pdf +0 -118
- data/data/pdfs/page_without_mediabox.pdf +0 -193
- data/data/pdfs/resources_as_indirect_object.pdf +0 -83
- data/data/pdfs/two_hexagons.pdf +0 -90
- data/data/pdfs/version_1_6.pdf +0 -61
- data/data/shift_jis_text.txt +0 -1
- data/lib/prawn/document/graphics_state.rb +0 -73
- data/lib/prawn/font/afm.rb +0 -247
- data/lib/prawn/table/cell/image.rb +0 -69
- data/lib/prawn/table/cell/in_table.rb +0 -33
- data/lib/prawn/table/cell/span_dummy.rb +0 -93
- data/lib/prawn/table/cell/subtable.rb +0 -66
- data/lib/prawn/table/cell/text.rb +0 -154
- data/lib/prawn/table/cell.rb +0 -772
- data/lib/prawn/table/cells.rb +0 -255
- data/lib/prawn/table/column_width_calculator.rb +0 -182
- data/lib/prawn/table.rb +0 -644
- data/manual/table/basic_block.rb +0 -53
- data/manual/table/before_rendering_page.rb +0 -26
- data/manual/table/cell_border_lines.rb +0 -24
- data/manual/table/cell_borders_and_bg.rb +0 -31
- data/manual/table/cell_dimensions.rb +0 -30
- data/manual/table/cell_text.rb +0 -38
- data/manual/table/column_widths.rb +0 -30
- data/manual/table/content_and_subtables.rb +0 -39
- data/manual/table/creation.rb +0 -27
- data/manual/table/filtering.rb +0 -36
- data/manual/table/flow_and_header.rb +0 -17
- data/manual/table/image_cells.rb +0 -33
- data/manual/table/position.rb +0 -29
- data/manual/table/row_colors.rb +0 -20
- data/manual/table/span.rb +0 -30
- data/manual/table/style.rb +0 -22
- data/manual/table/table.rb +0 -52
- data/manual/table/width.rb +0 -27
- data/spec/acceptance/png.rb +0 -25
- data/spec/annotations_spec.rb +0 -74
- data/spec/bounding_box_spec.rb +0 -510
- data/spec/cell_spec.rb +0 -629
- data/spec/column_box_spec.rb +0 -65
- data/spec/destinations_spec.rb +0 -15
- data/spec/document_spec.rb +0 -730
- data/spec/extensions/mocha.rb +0 -46
- data/spec/font_metric_cache_spec.rb +0 -52
- data/spec/font_spec.rb +0 -449
- data/spec/formatted_text_arranger_spec.rb +0 -421
- data/spec/formatted_text_box_spec.rb +0 -639
- data/spec/formatted_text_fragment_spec.rb +0 -298
- data/spec/graphics_spec.rb +0 -669
- data/spec/grid_spec.rb +0 -96
- data/spec/image_handler_spec.rb +0 -54
- data/spec/images_spec.rb +0 -153
- data/spec/inline_formatted_text_parser_spec.rb +0 -564
- data/spec/jpg_spec.rb +0 -25
- data/spec/line_wrap_spec.rb +0 -344
- data/spec/measurement_units_spec.rb +0 -25
- data/spec/outline_spec.rb +0 -430
- data/spec/png_spec.rb +0 -237
- data/spec/reference_spec.rb +0 -25
- data/spec/repeater_spec.rb +0 -160
- data/spec/security_spec.rb +0 -158
- data/spec/soft_mask_spec.rb +0 -79
- data/spec/span_spec.rb +0 -44
- data/spec/stamp_spec.rb +0 -160
- data/spec/stroke_styles_spec.rb +0 -211
- data/spec/table/span_dummy_spec.rb +0 -17
- data/spec/table_spec.rb +0 -1527
- data/spec/text_at_spec.rb +0 -115
- data/spec/text_box_spec.rb +0 -1034
- data/spec/text_rendering_mode_spec.rb +0 -45
- data/spec/text_spacing_spec.rb +0 -93
- data/spec/text_spec.rb +0 -437
- data/spec/text_with_inline_formatting_spec.rb +0 -35
- data/spec/transparency_spec.rb +0 -91
data/lib/prawn/text.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# text.rb : Implements PDF text primitives
|
4
4
|
#
|
@@ -6,25 +6,22 @@
|
|
6
6
|
#
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
|
9
|
-
require
|
9
|
+
require 'zlib'
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
require_relative "text/formatted"
|
14
|
-
require_relative "text/box"
|
11
|
+
require_relative 'text/formatted'
|
12
|
+
require_relative 'text/box'
|
15
13
|
|
16
14
|
module Prawn
|
17
15
|
module Text
|
18
|
-
|
19
16
|
include PDF::Core::Text
|
20
17
|
include Prawn::Text::Formatted
|
21
18
|
|
22
19
|
# No-Break Space
|
23
|
-
|
20
|
+
NBSP = "\u00A0"
|
24
21
|
# Zero Width Space (indicate word boundaries without a space)
|
25
|
-
|
22
|
+
ZWSP = "\u200B"
|
26
23
|
# Soft Hyphen (invisible, except when causing a line break)
|
27
|
-
|
24
|
+
SHY = "\u00AD"
|
28
25
|
|
29
26
|
# @group Stable API
|
30
27
|
|
@@ -116,7 +113,7 @@ module Prawn
|
|
116
113
|
# the current font familly. [current style]
|
117
114
|
# <tt>:indent_paragraphs</tt>:: <tt>number</tt>. The amount to indent the
|
118
115
|
# first line of each paragraph. Omit this
|
119
|
-
# option if you do not want indenting
|
116
|
+
# option if you do not want indenting.
|
120
117
|
# <tt>:direction</tt>::
|
121
118
|
# <tt>:ltr</tt>, <tt>:rtl</tt>, Direction of the text (left-to-right
|
122
119
|
# or right-to-left) [value of document.text_direction]
|
@@ -140,9 +137,9 @@ module Prawn
|
|
140
137
|
# each line is included below the last line;
|
141
138
|
# otherwise, document.y is placed just below the
|
142
139
|
# descender of the last line printed [true]
|
143
|
-
# <tt>:mode</tt>:: The text rendering mode to use. Use this to specify if
|
144
|
-
# text should render with the fill color, stroke color
|
145
|
-
# both. See the comments to text_rendering_mode() to see
|
140
|
+
# <tt>:mode</tt>:: The text rendering mode to use. Use this to specify if
|
141
|
+
# the text should render with the fill color, stroke color
|
142
|
+
# or both. See the comments to text_rendering_mode() to see
|
146
143
|
# a list of valid options. [0]
|
147
144
|
#
|
148
145
|
# == Exceptions
|
@@ -152,17 +149,19 @@ module Prawn
|
|
152
149
|
# Raises <tt>Prawn::Errrors::CannotFit</tt> if not wide enough to print
|
153
150
|
# any text
|
154
151
|
#
|
155
|
-
def text(string, options={})
|
152
|
+
def text(string, options = {})
|
156
153
|
return false if string.nil?
|
154
|
+
|
157
155
|
# we modify the options. don't change the user's hash
|
158
156
|
options = options.dup
|
159
157
|
|
160
|
-
|
158
|
+
p = options[:inline_format]
|
159
|
+
if p
|
161
160
|
p = [] unless p.is_a?(Array)
|
162
161
|
options.delete(:inline_format)
|
163
|
-
array =
|
162
|
+
array = text_formatter.format(string, *p)
|
164
163
|
else
|
165
|
-
array = [{ :
|
164
|
+
array = [{ text: string }]
|
166
165
|
end
|
167
166
|
|
168
167
|
formatted_text(array, options)
|
@@ -188,37 +187,33 @@ module Prawn
|
|
188
187
|
#
|
189
188
|
# Same as for #text
|
190
189
|
#
|
191
|
-
def formatted_text(array, options={})
|
190
|
+
def formatted_text(array, options = {})
|
192
191
|
options = inspect_options_for_text(options.dup)
|
193
192
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
193
|
+
color = options.delete(:color)
|
194
|
+
if color
|
195
|
+
array =
|
196
|
+
array.map do |fragment|
|
197
|
+
fragment[:color] ? fragment : fragment.merge(color: color)
|
198
|
+
end
|
198
199
|
end
|
199
200
|
|
200
201
|
if @indent_paragraphs
|
201
|
-
|
202
|
-
options[:skip_encoding] = false
|
202
|
+
text_formatter.array_paragraphs(array).each do |paragraph|
|
203
203
|
remaining_text = draw_indented_formatted_line(paragraph, options)
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
unless @all_text_printed
|
209
|
-
@bounding_box.move_past_bottom
|
210
|
-
options[:skip_encoding] = false
|
211
|
-
remaining_text = draw_indented_formatted_line(paragraph, options)
|
212
|
-
options[:skip_encoding] = true
|
213
|
-
end
|
204
|
+
|
205
|
+
if @no_text_printed && !@all_text_printed
|
206
|
+
@bounding_box.move_past_bottom
|
207
|
+
remaining_text = draw_indented_formatted_line(paragraph, options)
|
214
208
|
end
|
215
209
|
|
216
|
-
|
217
|
-
|
210
|
+
unless @all_text_printed
|
211
|
+
remaining_text = fill_formatted_text_box(remaining_text, options)
|
212
|
+
draw_remaining_formatted_text_on_new_pages(remaining_text, options)
|
213
|
+
end
|
218
214
|
end
|
219
215
|
else
|
220
216
|
remaining_text = fill_formatted_text_box(array, options)
|
221
|
-
options[:skip_encoding] = true
|
222
217
|
draw_remaining_formatted_text_on_new_pages(remaining_text, options)
|
223
218
|
end
|
224
219
|
end
|
@@ -242,7 +237,8 @@ module Prawn
|
|
242
237
|
# == Rotation
|
243
238
|
#
|
244
239
|
# Text can be rotated before it is placed on the canvas by specifying the
|
245
|
-
# <tt>:rotate</tt> option with a given angle. Rotation occurs
|
240
|
+
# <tt>:rotate</tt> option with a given angle. Rotation occurs
|
241
|
+
# counter-clockwise.
|
246
242
|
#
|
247
243
|
# == Encoding
|
248
244
|
#
|
@@ -259,7 +255,8 @@ module Prawn
|
|
259
255
|
#
|
260
256
|
# == Options (default values marked in [])
|
261
257
|
#
|
262
|
-
# <tt>:at</tt>:: <tt>[x, y]</tt>(required). The position at which to start
|
258
|
+
# <tt>:at</tt>:: <tt>[x, y]</tt>(required). The position at which to start
|
259
|
+
# the text
|
263
260
|
# <tt>:kerning</tt>:: <tt>boolean</tt>. Whether or not to use kerning (if it
|
264
261
|
# is available with the current font)
|
265
262
|
# [value of default_kerning?]
|
@@ -283,11 +280,29 @@ module Prawn
|
|
283
280
|
text = text.to_s.dup
|
284
281
|
save_font do
|
285
282
|
process_text_options(options)
|
286
|
-
font.normalize_encoding
|
283
|
+
text = font.normalize_encoding(text)
|
287
284
|
font_size(options[:size]) { draw_text!(text, options) }
|
288
285
|
end
|
289
286
|
end
|
290
287
|
|
288
|
+
# Low level text placement method. All font and size alterations
|
289
|
+
# should already be set
|
290
|
+
#
|
291
|
+
def draw_text!(text, options)
|
292
|
+
unless font.unicode? || font.class.hide_m17n_warning || text.ascii_only?
|
293
|
+
warn "PDF's built-in fonts have very limited support for " \
|
294
|
+
"internationalized text.\nIf you need full UTF-8 support, " \
|
295
|
+
"consider using an external font instead.\n\nTo disable this " \
|
296
|
+
"warning, add the following line to your code:\n" \
|
297
|
+
"Prawn::Fonts::AFM.hide_m17n_warning = true\n"
|
298
|
+
|
299
|
+
font.class.hide_m17n_warning = true
|
300
|
+
end
|
301
|
+
|
302
|
+
x, y = map_to_absolute(options[:at])
|
303
|
+
add_text_content(text, x, y, options)
|
304
|
+
end
|
305
|
+
|
291
306
|
# Gets height of text in PDF points.
|
292
307
|
# Same options as #text, except as noted.
|
293
308
|
# Not compatible with :indent_paragraphs option
|
@@ -304,8 +319,8 @@ module Prawn
|
|
304
319
|
# Raises <tt>Prawn::Errrors::CannotFit</tt> if not wide enough to print
|
305
320
|
# any text
|
306
321
|
#
|
307
|
-
def height_of(string, options={})
|
308
|
-
height_of_formatted([{ :
|
322
|
+
def height_of(string, options = {})
|
323
|
+
height_of_formatted([{ text: string }], options)
|
309
324
|
end
|
310
325
|
|
311
326
|
# Gets height of formatted text in PDF points.
|
@@ -318,16 +333,17 @@ module Prawn
|
|
318
333
|
# :size => 24,
|
319
334
|
# :styles => [:bold, :italic] }])
|
320
335
|
#
|
321
|
-
def height_of_formatted(array, options={})
|
336
|
+
def height_of_formatted(array, options = {})
|
322
337
|
if options[:indent_paragraphs]
|
323
|
-
raise NotImplementedError,
|
324
|
-
|
338
|
+
raise NotImplementedError,
|
339
|
+
':indent_paragraphs option not available with height_of'
|
325
340
|
end
|
326
341
|
process_final_gap_option(options)
|
327
|
-
box = Text::Formatted::Box.new(
|
328
|
-
|
329
|
-
|
330
|
-
|
342
|
+
box = Text::Formatted::Box.new(
|
343
|
+
array,
|
344
|
+
options.merge(height: 100_000_000, document: self)
|
345
|
+
)
|
346
|
+
box.render(dry_run: true)
|
331
347
|
|
332
348
|
height = box.height
|
333
349
|
height += box.line_gap + box.leading if @final_gap
|
@@ -337,7 +353,7 @@ module Prawn
|
|
337
353
|
private
|
338
354
|
|
339
355
|
def draw_remaining_formatted_text_on_new_pages(remaining_text, options)
|
340
|
-
|
356
|
+
until remaining_text.empty?
|
341
357
|
@bounding_box.move_past_bottom
|
342
358
|
previous_remaining_text = remaining_text
|
343
359
|
remaining_text = fill_formatted_text_box(remaining_text, options)
|
@@ -346,8 +362,15 @@ module Prawn
|
|
346
362
|
end
|
347
363
|
|
348
364
|
def draw_indented_formatted_line(string, options)
|
349
|
-
|
350
|
-
|
365
|
+
gap =
|
366
|
+
if options.fetch(:direction, text_direction) == :ltr
|
367
|
+
[@indent_paragraphs, 0]
|
368
|
+
else
|
369
|
+
[0, @indent_paragraphs]
|
370
|
+
end
|
371
|
+
|
372
|
+
indent(*gap) do
|
373
|
+
fill_formatted_text_box(string, options.dup.merge(single_line: true))
|
351
374
|
end
|
352
375
|
end
|
353
376
|
|
@@ -365,33 +388,41 @@ module Prawn
|
|
365
388
|
end
|
366
389
|
|
367
390
|
def merge_text_box_positioning_options(options)
|
368
|
-
bottom =
|
369
|
-
|
391
|
+
bottom =
|
392
|
+
if @bounding_box.stretchy?
|
393
|
+
@margin_box.absolute_bottom
|
394
|
+
else
|
395
|
+
@bounding_box.absolute_bottom
|
396
|
+
end
|
370
397
|
|
371
398
|
options[:height] = y - bottom
|
372
399
|
options[:width] = bounds.width
|
373
|
-
options[:at] = [
|
374
|
-
|
400
|
+
options[:at] = [
|
401
|
+
@bounding_box.left_side - @bounding_box.absolute_left,
|
402
|
+
y - @bounding_box.absolute_bottom
|
403
|
+
]
|
375
404
|
end
|
376
405
|
|
377
406
|
def inspect_options_for_draw_text(options)
|
378
407
|
if options[:at].nil?
|
379
|
-
raise ArgumentError,
|
408
|
+
raise ArgumentError, 'The :at option is required for draw_text'
|
380
409
|
elsif options[:align]
|
381
|
-
raise ArgumentError,
|
410
|
+
raise ArgumentError, 'The :align option does not work with draw_text'
|
382
411
|
end
|
383
|
-
|
412
|
+
|
413
|
+
if options[:kerning].nil?
|
384
414
|
options[:kerning] = default_kerning?
|
385
415
|
end
|
386
|
-
valid_options = PDF::Core::Text::VALID_OPTIONS + [
|
416
|
+
valid_options = PDF::Core::Text::VALID_OPTIONS + %i[at rotate]
|
387
417
|
Prawn.verify_options(valid_options, options)
|
388
418
|
options
|
389
419
|
end
|
390
420
|
|
391
421
|
def inspect_options_for_text(options)
|
392
422
|
if options[:at]
|
393
|
-
raise ArgumentError,
|
394
|
-
|
423
|
+
raise ArgumentError,
|
424
|
+
':at is no longer a valid option with text.' \
|
425
|
+
'use draw_text or text_box instead'
|
395
426
|
end
|
396
427
|
process_final_gap_option(options)
|
397
428
|
process_indent_paragraphs_option(options)
|
@@ -409,13 +440,17 @@ module Prawn
|
|
409
440
|
options.delete(:indent_paragraphs)
|
410
441
|
end
|
411
442
|
|
412
|
-
def move_text_position(
|
413
|
-
bottom =
|
414
|
-
|
443
|
+
def move_text_position(amount)
|
444
|
+
bottom =
|
445
|
+
if @bounding_box.stretchy?
|
446
|
+
@margin_box.absolute_bottom
|
447
|
+
else
|
448
|
+
@bounding_box.absolute_bottom
|
449
|
+
end
|
415
450
|
|
416
|
-
@bounding_box.move_past_bottom if (y -
|
451
|
+
@bounding_box.move_past_bottom if (y - amount) < bottom
|
417
452
|
|
418
|
-
self.y -=
|
453
|
+
self.y -= amount
|
419
454
|
end
|
420
455
|
end
|
421
456
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# transformation_stack.rb : Stores the transformations that have been applied to
|
4
|
+
# the document
|
5
|
+
#
|
6
|
+
# Copyright 2015, Roger Nesbitt. All Rights Reserved.
|
7
|
+
#
|
8
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
9
|
+
|
10
|
+
require 'matrix'
|
11
|
+
|
12
|
+
# rubocop: disable Metrics/ParameterLists, Naming/MethodParameterName
|
13
|
+
module Prawn
|
14
|
+
module TransformationStack
|
15
|
+
def add_to_transformation_stack(a, b, c, d, e, f)
|
16
|
+
@transformation_stack ||= [[]]
|
17
|
+
@transformation_stack.last.push([a, b, c, d, e, f].map(&:to_f))
|
18
|
+
end
|
19
|
+
|
20
|
+
def save_transformation_stack
|
21
|
+
@transformation_stack ||= [[]]
|
22
|
+
@transformation_stack.push(@transformation_stack.last.dup)
|
23
|
+
end
|
24
|
+
|
25
|
+
def restore_transformation_stack
|
26
|
+
@transformation_stack&.pop
|
27
|
+
end
|
28
|
+
|
29
|
+
def current_transformation_matrix_with_translation(x = 0, y = 0)
|
30
|
+
transformations = (@transformation_stack || [[]]).last
|
31
|
+
|
32
|
+
matrix = Matrix.identity(3)
|
33
|
+
|
34
|
+
transformations.each do |a, b, c, d, e, f|
|
35
|
+
matrix *= Matrix[[a, c, e], [b, d, f], [0, 0, 1]]
|
36
|
+
end
|
37
|
+
|
38
|
+
matrix *= Matrix[[1, 0, x], [0, 1, y], [0, 0, 1]]
|
39
|
+
|
40
|
+
matrix.to_a[0..1].transpose.flatten
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# rubocop: enable Metrics/ParameterLists, Naming/MethodParameterName
|
data/lib/prawn/utilities.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# utilities.rb : General-purpose utility classes which don't fit anywhere else
|
4
4
|
#
|
@@ -6,41 +6,29 @@
|
|
6
6
|
#
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
|
9
|
-
require 'thread'
|
10
|
-
|
11
9
|
module Prawn
|
12
|
-
|
13
|
-
#
|
14
|
-
# In some cases, caching and reusing results can not only save CPU cycles but
|
15
|
-
#
|
10
|
+
# Throughout the Prawn codebase, repeated calculations which can benefit from
|
11
|
+
# caching are made.
|
12
|
+
# In some cases, caching and reusing results can not only save CPU cycles but
|
13
|
+
# also greatly reduce memory requirements
|
16
14
|
# But at the same time, we don't want to throw away thread safety
|
17
15
|
# We have two interchangeable thread-safe cache implementations:
|
18
16
|
|
19
17
|
# @private
|
20
18
|
class SynchronizedCache
|
21
|
-
# As an optimization, this could access the hash directly on VMs with
|
19
|
+
# As an optimization, this could access the hash directly on VMs with
|
20
|
+
# a global interpreter lock (like MRI)
|
22
21
|
def initialize
|
23
22
|
@cache = {}
|
24
23
|
@mutex = Mutex.new
|
25
24
|
end
|
25
|
+
|
26
26
|
def [](key)
|
27
27
|
@mutex.synchronize { @cache[key] }
|
28
28
|
end
|
29
|
-
def []=(key,value)
|
30
|
-
@mutex.synchronize { @cache[key] = value }
|
31
|
-
end
|
32
|
-
end
|
33
29
|
|
34
|
-
|
35
|
-
|
36
|
-
def initialize
|
37
|
-
@cache_id = "cache_#{self.object_id}".to_sym
|
38
|
-
end
|
39
|
-
def [](key)
|
40
|
-
(Thread.current[@cache_id] ||= {})[key]
|
41
|
-
end
|
42
|
-
def []=(key,value)
|
43
|
-
(Thread.current[@cache_id] ||= {})[key] = value
|
30
|
+
def []=(key, value)
|
31
|
+
@mutex.synchronize { @cache[key] = value }
|
44
32
|
end
|
45
33
|
end
|
46
34
|
end
|
data/lib/prawn/view.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# prawn/view.rb : Implements a mixin for Prawn's DSL
|
4
|
+
#
|
5
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
6
|
+
|
7
|
+
module Prawn
|
8
|
+
# This mixin allows you to create modular Prawn code without the
|
9
|
+
# need to create subclasses of Prawn::Document.
|
10
|
+
#
|
11
|
+
# class Greeter
|
12
|
+
# include Prawn::View
|
13
|
+
#
|
14
|
+
# # Optional override: allows you to set document options or even use
|
15
|
+
# # a custom document class
|
16
|
+
# def document
|
17
|
+
# @document ||= Prawn::Document.new(page_size: 'A4')
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def initialize(name)
|
21
|
+
# @name = name
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# def say_hello
|
25
|
+
# text "Hello, #{@name}!"
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# def say_goodbye
|
29
|
+
# font("Courier") do
|
30
|
+
# text "Goodbye, #{@name}!"
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# greeter = Greeter.new("Gregory")
|
36
|
+
#
|
37
|
+
# greeter.say_hello
|
38
|
+
# greeter.say_goodbye
|
39
|
+
#
|
40
|
+
# greeter.save_as("greetings.pdf")
|
41
|
+
#
|
42
|
+
# The short story about why you should use this mixin rather than
|
43
|
+
# creating subclasses of +Prawn::Document+ is that it helps
|
44
|
+
# prevent accidental conflicts between your code and Prawn's
|
45
|
+
# code.
|
46
|
+
#
|
47
|
+
# Here's the slightly longer story...
|
48
|
+
#
|
49
|
+
# By using composition rather than inheritance under the hood, this
|
50
|
+
# mixin allows you to keep your state separate from +Prawn::Document+'s
|
51
|
+
# state, and also will prevent unexpected method name collisions due
|
52
|
+
# to late binding effects.
|
53
|
+
#
|
54
|
+
# This mixin is mostly meant for extending Prawn's functionality
|
55
|
+
# with your own additions, but you can also use it to replace or
|
56
|
+
# wrap existing Prawn methods. Calling +super+ will still work
|
57
|
+
# as expected, and alternatively you can explictly call
|
58
|
+
# +document.some_method+ to delegate to Prawn where needed.
|
59
|
+
module View
|
60
|
+
# @group Experimental API
|
61
|
+
|
62
|
+
# Lazily instantiates a +Prawn::Document+ object.
|
63
|
+
#
|
64
|
+
# You can also redefine this method in your own classes to use
|
65
|
+
# a custom document class.
|
66
|
+
def document
|
67
|
+
@document ||= Prawn::Document.new
|
68
|
+
end
|
69
|
+
|
70
|
+
# Delegates all unhandled calls to object returned by +document+ method.
|
71
|
+
# (which is an instance of Prawn::Document by default)
|
72
|
+
def method_missing(method_name, *arguments, &block)
|
73
|
+
return super unless document.respond_to?(method_name)
|
74
|
+
|
75
|
+
document.public_send(method_name, *arguments, &block)
|
76
|
+
end
|
77
|
+
|
78
|
+
def respond_to_missing?(method_name, _include_all = false)
|
79
|
+
document.respond_to?(method_name) || super
|
80
|
+
end
|
81
|
+
|
82
|
+
# Syntactic sugar that uses +instance_eval+ under the hood to provide
|
83
|
+
# a block-based DSL.
|
84
|
+
#
|
85
|
+
# greeter.update do
|
86
|
+
# say_hello
|
87
|
+
# say_goodbye
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
def update(&block)
|
91
|
+
instance_eval(&block)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Syntatic sugar that calls +document.render_file+ under the hood.
|
95
|
+
#
|
96
|
+
# greeter.save_as("greetings.pdf")
|
97
|
+
def save_as(filename)
|
98
|
+
document.render_file(filename)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/prawn.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Welcome to Prawn, the best PDF Generation library ever.
|
4
4
|
# This documentation covers user level functionality.
|
5
5
|
#
|
6
|
-
require
|
6
|
+
require 'set'
|
7
7
|
|
8
8
|
require 'ttfunk'
|
9
|
-
require
|
9
|
+
require 'pdf/core'
|
10
10
|
|
11
11
|
module Prawn
|
12
|
-
VERSION = "1.1.0"
|
13
|
-
|
14
|
-
extend self
|
15
|
-
|
16
12
|
file = __FILE__
|
17
13
|
file = File.readlink(file) if File.symlink?(file)
|
18
|
-
dir
|
14
|
+
dir = File.dirname(file)
|
19
15
|
|
20
16
|
# The base source directory for Prawn as installed on the system
|
21
17
|
#
|
@@ -25,7 +21,7 @@ module Prawn
|
|
25
21
|
|
26
22
|
FLOAT_PRECISION = 1.0e-9
|
27
23
|
|
28
|
-
#
|
24
|
+
# When set to true, Prawn will verify hash options to ensure only valid keys
|
29
25
|
# are used. Off by default.
|
30
26
|
#
|
31
27
|
# Example:
|
@@ -34,60 +30,49 @@ module Prawn
|
|
34
30
|
# Detected unknown option(s): [:tomato]
|
35
31
|
# Accepted options are: [:page_size, :page_layout, :left_margin, ...]
|
36
32
|
#
|
37
|
-
|
33
|
+
# @private
|
34
|
+
attr_accessor :debug
|
35
|
+
|
36
|
+
module_function :debug, :debug=
|
37
|
+
|
38
|
+
module_function
|
38
39
|
|
39
|
-
|
40
|
+
# @private
|
41
|
+
def verify_options(accepted, actual)
|
40
42
|
return unless debug || $DEBUG
|
41
|
-
|
43
|
+
|
44
|
+
unless (act = Set[*actual.keys]).subset?(acc = Set[*accepted])
|
42
45
|
raise Prawn::Errors::UnknownOption,
|
43
|
-
"\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n"
|
46
|
+
"\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n" \
|
44
47
|
"Accepted options are: #{accepted.inspect}"
|
45
48
|
end
|
46
49
|
yield if block_given?
|
47
50
|
end
|
48
|
-
|
49
|
-
module Configurable # @private
|
50
|
-
def configuration(*args)
|
51
|
-
@config ||= Marshal.load(Marshal.dump(default_configuration))
|
52
|
-
if Hash === args[0]
|
53
|
-
@config.update(args[0])
|
54
|
-
elsif args.length > 1
|
55
|
-
@config.values_at(*args)
|
56
|
-
elsif args.length == 1
|
57
|
-
@config[args[0]]
|
58
|
-
else
|
59
|
-
@config
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
alias_method :C, :configuration
|
64
|
-
end
|
65
51
|
end
|
66
52
|
|
67
|
-
require_relative
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
require_relative
|
72
|
-
require_relative
|
73
|
-
require_relative
|
74
|
-
require_relative
|
75
|
-
require_relative
|
76
|
-
require_relative
|
77
|
-
require_relative
|
78
|
-
require_relative
|
79
|
-
require_relative
|
80
|
-
require_relative
|
81
|
-
require_relative
|
82
|
-
require_relative
|
83
|
-
require_relative
|
84
|
-
require_relative
|
85
|
-
require_relative
|
86
|
-
require_relative
|
87
|
-
|
88
|
-
require_relative
|
89
|
-
|
90
|
-
|
53
|
+
require_relative 'prawn/version'
|
54
|
+
|
55
|
+
require_relative 'prawn/errors'
|
56
|
+
|
57
|
+
require_relative 'prawn/utilities'
|
58
|
+
require_relative 'prawn/text'
|
59
|
+
require_relative 'prawn/graphics'
|
60
|
+
require_relative 'prawn/images'
|
61
|
+
require_relative 'prawn/images/image'
|
62
|
+
require_relative 'prawn/images/jpg'
|
63
|
+
require_relative 'prawn/images/png'
|
64
|
+
require_relative 'prawn/stamp'
|
65
|
+
require_relative 'prawn/soft_mask'
|
66
|
+
require_relative 'prawn/security'
|
67
|
+
require_relative 'prawn/transformation_stack'
|
68
|
+
require_relative 'prawn/document'
|
69
|
+
require_relative 'prawn/font'
|
70
|
+
require_relative 'prawn/measurements'
|
71
|
+
require_relative 'prawn/repeater'
|
72
|
+
require_relative 'prawn/outline'
|
73
|
+
require_relative 'prawn/grid'
|
74
|
+
require_relative 'prawn/view'
|
75
|
+
require_relative 'prawn/image_handler'
|
91
76
|
|
92
77
|
Prawn.image_handler.register(Prawn::Images::PNG)
|
93
78
|
Prawn.image_handler.register(Prawn::Images::JPG)
|