prawn 2.0.2 → 2.3.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.tar.gz.sig +0 -0
- data/GPLv2 +20 -21
- data/Gemfile +3 -9
- data/Rakefile +20 -23
- data/lib/prawn.rb +37 -49
- data/lib/prawn/document.rb +181 -133
- data/lib/prawn/document/bounding_box.rb +41 -29
- data/lib/prawn/document/column_box.rb +7 -7
- data/lib/prawn/document/internals.rb +18 -8
- data/lib/prawn/document/span.rb +21 -16
- data/lib/prawn/encoding.rb +69 -68
- data/lib/prawn/errors.rb +12 -7
- data/lib/prawn/font.rb +115 -69
- data/lib/prawn/font_metric_cache.rb +14 -8
- data/lib/prawn/{font → fonts}/afm.rb +102 -68
- data/lib/prawn/{font → fonts}/dfont.rb +5 -11
- data/lib/prawn/fonts/otf.rb +11 -0
- data/lib/prawn/fonts/ttc.rb +36 -0
- data/lib/prawn/{font → fonts}/ttf.rb +87 -68
- data/lib/prawn/graphics.rb +120 -80
- data/lib/prawn/graphics/blend_mode.rb +65 -0
- data/lib/prawn/graphics/cap_style.rb +3 -3
- data/lib/prawn/graphics/color.rb +27 -25
- data/lib/prawn/graphics/dash.rb +23 -11
- data/lib/prawn/graphics/join_style.rb +9 -3
- data/lib/prawn/graphics/patterns.rb +197 -67
- data/lib/prawn/graphics/transformation.rb +17 -8
- data/lib/prawn/graphics/transparency.rb +17 -13
- data/lib/prawn/grid.rb +48 -47
- data/lib/prawn/image_handler.rb +5 -5
- data/lib/prawn/images.rb +39 -30
- data/lib/prawn/images/image.rb +2 -1
- data/lib/prawn/images/jpg.rb +28 -22
- data/lib/prawn/images/png.rb +107 -66
- data/lib/prawn/measurement_extensions.rb +10 -9
- data/lib/prawn/measurements.rb +19 -15
- data/lib/prawn/outline.rb +97 -77
- data/lib/prawn/repeater.rb +14 -10
- data/lib/prawn/security.rb +81 -61
- data/lib/prawn/security/arcfour.rb +2 -2
- data/lib/prawn/soft_mask.rb +26 -26
- data/lib/prawn/stamp.rb +20 -13
- data/lib/prawn/text.rb +68 -52
- data/lib/prawn/text/box.rb +11 -8
- data/lib/prawn/text/formatted.rb +5 -5
- data/lib/prawn/text/formatted/arranger.rb +78 -49
- data/lib/prawn/text/formatted/box.rb +134 -100
- data/lib/prawn/text/formatted/fragment.rb +11 -14
- data/lib/prawn/text/formatted/line_wrap.rb +121 -63
- data/lib/prawn/text/formatted/parser.rb +139 -117
- data/lib/prawn/text/formatted/wrap.rb +43 -31
- data/lib/prawn/transformation_stack.rb +44 -0
- data/lib/prawn/utilities.rb +7 -22
- data/lib/prawn/version.rb +2 -2
- data/lib/prawn/view.rb +17 -7
- data/manual/basic_concepts/adding_pages.rb +6 -7
- data/manual/basic_concepts/basic_concepts.rb +31 -22
- data/manual/basic_concepts/creation.rb +10 -11
- data/manual/basic_concepts/cursor.rb +4 -5
- data/manual/basic_concepts/measurement.rb +6 -7
- data/manual/basic_concepts/origin.rb +5 -6
- data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
- data/manual/basic_concepts/view.rb +22 -16
- data/manual/bounding_box/bounding_box.rb +29 -24
- data/manual/bounding_box/bounds.rb +11 -12
- data/manual/bounding_box/canvas.rb +4 -5
- data/manual/bounding_box/creation.rb +6 -7
- data/manual/bounding_box/indentation.rb +14 -15
- data/manual/bounding_box/nesting.rb +24 -17
- data/manual/bounding_box/russian_boxes.rb +14 -13
- data/manual/bounding_box/stretchy.rb +12 -13
- data/manual/contents.rb +28 -22
- data/manual/cover.rb +33 -28
- data/manual/document_and_page_options/background.rb +11 -13
- data/manual/document_and_page_options/document_and_page_options.rb +25 -20
- data/manual/document_and_page_options/metadata.rb +18 -16
- data/manual/document_and_page_options/page_margins.rb +18 -20
- data/manual/document_and_page_options/page_size.rb +13 -12
- data/manual/document_and_page_options/print_scaling.rb +17 -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 +4 -5
- data/manual/graphics/fill_rules.rb +9 -10
- data/manual/graphics/gradients.rb +27 -21
- data/manual/graphics/graphics.rb +48 -39
- data/manual/graphics/helper.rb +12 -9
- data/manual/graphics/line_width.rb +8 -7
- data/manual/graphics/lines_and_curves.rb +7 -8
- data/manual/graphics/polygon.rb +6 -8
- data/manual/graphics/rectangle.rb +4 -5
- data/manual/graphics/rotate.rb +6 -7
- data/manual/graphics/scale.rb +14 -15
- data/manual/graphics/soft_masks.rb +4 -5
- data/manual/graphics/stroke_cap.rb +6 -7
- data/manual/graphics/stroke_dash.rb +11 -12
- data/manual/graphics/stroke_join.rb +5 -6
- data/manual/graphics/translate.rb +9 -10
- data/manual/graphics/transparency.rb +7 -8
- data/manual/how_to_read_this_manual.rb +6 -6
- data/manual/images/absolute_position.rb +6 -7
- data/manual/images/fit.rb +7 -8
- data/manual/images/horizontal.rb +9 -10
- data/manual/images/images.rb +28 -24
- data/manual/images/plain_image.rb +5 -6
- data/manual/images/scale.rb +9 -10
- data/manual/images/vertical.rb +13 -14
- data/manual/images/width_and_height.rb +10 -11
- data/manual/layout/boxes.rb +5 -6
- data/manual/layout/content.rb +7 -8
- data/manual/layout/layout.rb +18 -16
- 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 +21 -17
- data/manual/outline/sections_and_pages.rb +17 -18
- data/manual/repeatable_content/alternate_page_numbering.rb +21 -17
- data/manual/repeatable_content/page_numbering.rb +17 -16
- data/manual/repeatable_content/repeatable_content.rb +25 -19
- data/manual/repeatable_content/repeater.rb +14 -15
- data/manual/repeatable_content/stamp.rb +14 -15
- data/manual/security/encryption.rb +9 -10
- data/manual/security/permissions.rb +19 -14
- data/manual/security/security.rb +19 -16
- data/manual/table.rb +3 -3
- data/manual/text/alignment.rb +16 -17
- data/manual/text/color.rb +12 -11
- data/manual/text/column_box.rb +9 -10
- 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 +7 -8
- data/manual/text/formatted_callbacks.rb +25 -21
- data/manual/text/formatted_text.rb +33 -25
- data/manual/text/free_flowing_text.rb +20 -21
- 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 +13 -14
- data/manual/text/positioned_text.rb +15 -16
- data/manual/text/registering_families.rb +20 -21
- data/manual/text/rendering_and_color.rb +9 -10
- data/manual/text/right_to_left_text.rb +26 -19
- data/manual/text/rotation.rb +28 -23
- data/manual/text/single_usage.rb +8 -9
- data/manual/text/text.rb +57 -52
- 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 +18 -19
- data/manual/text/utf8.rb +11 -12
- data/manual/text/win_ansi_charset.rb +21 -19
- data/prawn.gemspec +45 -33
- data/spec/extensions/encoding_helpers.rb +3 -3
- data/spec/prawn/document/bounding_box_spec.rb +546 -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 +36 -0
- data/spec/prawn/document_spec.rb +802 -0
- data/spec/prawn/font_metric_cache_spec.rb +54 -0
- data/spec/prawn/font_spec.rb +542 -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 +837 -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 +224 -0
- data/spec/prawn/measurements_extensions_spec.rb +24 -0
- data/spec/prawn/outline_spec.rb +412 -0
- data/spec/prawn/repeater_spec.rb +165 -0
- data/spec/prawn/soft_mask_spec.rb +74 -0
- data/spec/prawn/stamp_spec.rb +172 -0
- data/spec/prawn/text/box_spec.rb +1112 -0
- data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
- data/spec/prawn/text/formatted/box_spec.rb +846 -0
- data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
- data/spec/prawn/text/formatted/line_wrap_spec.rb +494 -0
- data/spec/prawn/text/formatted/parser_spec.rb +697 -0
- data/spec/prawn/text_draw_text_spec.rb +149 -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 -23
- metadata +145 -185
- metadata.gz.sig +4 -0
- 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/pal_bk.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/spec/acceptance/png.rb +0 -24
- data/spec/annotations_spec.rb +0 -67
- data/spec/bounding_box_spec.rb +0 -501
- data/spec/column_box_spec.rb +0 -59
- data/spec/destinations_spec.rb +0 -13
- data/spec/document_spec.rb +0 -742
- data/spec/extensions/mocha.rb +0 -45
- data/spec/font_metric_cache_spec.rb +0 -52
- data/spec/font_spec.rb +0 -475
- data/spec/formatted_text_arranger_spec.rb +0 -423
- data/spec/formatted_text_box_spec.rb +0 -716
- data/spec/formatted_text_fragment_spec.rb +0 -299
- data/spec/graphics_spec.rb +0 -666
- data/spec/grid_spec.rb +0 -95
- data/spec/image_handler_spec.rb +0 -53
- data/spec/images_spec.rb +0 -167
- data/spec/inline_formatted_text_parser_spec.rb +0 -568
- data/spec/jpg_spec.rb +0 -23
- data/spec/line_wrap_spec.rb +0 -366
- data/spec/measurement_units_spec.rb +0 -22
- data/spec/outline_spec.rb +0 -409
- data/spec/png_spec.rb +0 -235
- data/spec/reference_spec.rb +0 -25
- data/spec/repeater_spec.rb +0 -154
- data/spec/security_spec.rb +0 -151
- data/spec/soft_mask_spec.rb +0 -78
- data/spec/span_spec.rb +0 -43
- data/spec/stamp_spec.rb +0 -179
- data/spec/stroke_styles_spec.rb +0 -208
- data/spec/text_at_spec.rb +0 -142
- data/spec/text_box_spec.rb +0 -1038
- data/spec/text_rendering_mode_spec.rb +0 -45
- data/spec/text_spacing_spec.rb +0 -93
- data/spec/text_spec.rb +0 -549
- data/spec/text_with_inline_formatting_spec.rb +0 -35
- data/spec/transparency_spec.rb +0 -91
- data/spec/view_spec.rb +0 -42
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
# Whenever the <code>text_box</code> method truncates text, this truncated bit
|
4
4
|
# is not lost, it is the method return value and we can take advantage of that.
|
5
5
|
#
|
@@ -8,25 +8,28 @@
|
|
8
8
|
# This example renders as much of the text as will fit in a larger font inside
|
9
9
|
# one text_box and then proceeds to render the remaining text in the default
|
10
10
|
# size in a second text_box.
|
11
|
-
|
12
|
-
require
|
13
|
-
%w[.. example_helper]))
|
11
|
+
|
12
|
+
require '../example_helper'
|
14
13
|
|
15
14
|
filename = File.basename(__FILE__).gsub('.rb', '.pdf')
|
16
15
|
Prawn::ManualBuilder::Example.generate(filename) do
|
17
|
-
string =
|
18
|
-
|
19
|
-
|
16
|
+
string = 'This is the beginning of the text. It will be cut somewhere and ' \
|
17
|
+
'the rest of the text will procede to be rendered this time by ' \
|
18
|
+
'calling another method.' + ' . ' * 50
|
20
19
|
|
21
20
|
y_position = cursor - 20
|
22
|
-
excess_text = text_box
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
excess_text = text_box(
|
22
|
+
string,
|
23
|
+
width: 300,
|
24
|
+
height: 50,
|
25
|
+
overflow: :truncate,
|
26
|
+
at: [100, y_position],
|
27
|
+
size: 18
|
28
|
+
)
|
28
29
|
|
29
|
-
text_box
|
30
|
-
|
31
|
-
|
30
|
+
text_box(
|
31
|
+
excess_text,
|
32
|
+
width: 300,
|
33
|
+
at: [100, y_position - 100]
|
34
|
+
)
|
32
35
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
# We've already seen one way of using text boxes with the <code>text_box</code>
|
4
4
|
# method. Turns out this method is just a convenience for using the
|
5
5
|
# <code>Prawn::Text::Box</code> class as it creates a new object and call
|
@@ -9,9 +9,8 @@
|
|
9
9
|
# effect when we use the <code>text_box</code> method. To add an extension all
|
10
10
|
# we need to do is append the <code>Prawn::Text::Box.extensions</code> array
|
11
11
|
# with a module.
|
12
|
-
|
13
|
-
require
|
14
|
-
%w[.. example_helper]))
|
12
|
+
|
13
|
+
require '../example_helper'
|
15
14
|
|
16
15
|
filename = File.basename(__FILE__).gsub('.rb', '.pdf')
|
17
16
|
Prawn::ManualBuilder::Example.generate(filename) do
|
@@ -22,22 +21,26 @@ Prawn::ManualBuilder::Example.generate(filename) do
|
|
22
21
|
end
|
23
22
|
|
24
23
|
y_position = cursor - 10
|
25
|
-
width
|
26
|
-
height
|
24
|
+
width = 100
|
25
|
+
height = 100
|
27
26
|
|
28
27
|
Prawn::Text::Box.extensions << TriangleBox
|
29
28
|
stroke_rectangle([0, y_position], width, height)
|
30
|
-
text_box(
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
text_box(
|
30
|
+
'A' * 100,
|
31
|
+
at: [0, y_position],
|
32
|
+
width: width,
|
33
|
+
height: height
|
34
|
+
)
|
34
35
|
|
35
36
|
Prawn::Text::Formatted::Box.extensions << TriangleBox
|
36
37
|
stroke_rectangle([200, y_position], width, height)
|
37
|
-
formatted_text_box(
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
formatted_text_box(
|
39
|
+
[text: 'A' * 100, color: '009900'],
|
40
|
+
at: [200, y_position],
|
41
|
+
width: width,
|
42
|
+
height: height
|
43
|
+
)
|
41
44
|
|
42
45
|
# Here we clear the extensions array
|
43
46
|
Prawn::Text::Box.extensions.clear
|
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
# The <code>text_box</code> method accepts both <code>:width</code> and
|
4
4
|
# <code>:height</code> options. So what happens if the text doesn't fit the box?
|
5
5
|
#
|
@@ -15,36 +15,35 @@
|
|
15
15
|
# If the <code>:disable_wrap_by_char</code> is set to <code>true</code>
|
16
16
|
# then any text wrapping done while using the <code>:shrink_to_fit</code>
|
17
17
|
# mode will not break up the middle of words.
|
18
|
-
|
19
|
-
|
20
|
-
%w[.. example_helper]))
|
18
|
+
|
19
|
+
require_relative '../example_helper'
|
21
20
|
|
22
21
|
filename = File.basename(__FILE__).gsub('.rb', '.pdf')
|
23
22
|
Prawn::ManualBuilder::Example.generate(filename) do
|
24
|
-
string =
|
25
|
-
|
23
|
+
string = 'This is the sample text used for the text boxes. See how it ' \
|
24
|
+
'behave with the various overflow options used.'
|
26
25
|
|
27
26
|
text string
|
28
27
|
|
29
28
|
y_position = cursor - 20
|
30
|
-
[
|
31
|
-
text_box string, :
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
29
|
+
%i[truncate expand shrink_to_fit].each_with_index do |mode, i|
|
30
|
+
text_box string, at: [i * 150, y_position],
|
31
|
+
width: 100,
|
32
|
+
height: 50,
|
33
|
+
overflow: mode
|
35
34
|
end
|
36
35
|
|
37
|
-
string =
|
38
|
-
|
36
|
+
string = 'If the box is too small for the text, :shrink_to_fit ' \
|
37
|
+
'can render the text in a really small font size.'
|
39
38
|
|
40
39
|
move_down 120
|
41
40
|
text string
|
42
41
|
y_position = cursor - 20
|
43
42
|
[nil, 8, 10, 12].each_with_index do |value, index|
|
44
|
-
text_box string, :
|
45
|
-
:
|
46
|
-
:
|
47
|
-
:
|
48
|
-
:
|
43
|
+
text_box string, at: [index * 150, y_position],
|
44
|
+
width: 50,
|
45
|
+
height: 50,
|
46
|
+
overflow: :shrink_to_fit,
|
47
|
+
min_font_size: value
|
49
48
|
end
|
50
49
|
end
|
data/manual/text/utf8.rb
CHANGED
@@ -1,28 +1,27 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
# Multilingualization isn't much of a problem on Prawn as its default encoding
|
4
4
|
# is UTF-8. The only thing you need to worry about is if the font support the
|
5
5
|
# glyphs of your language.
|
6
|
-
|
7
|
-
|
8
|
-
%w[.. example_helper]))
|
6
|
+
|
7
|
+
require_relative '../example_helper'
|
9
8
|
|
10
9
|
filename = File.basename(__FILE__).gsub('.rb', '.pdf')
|
11
10
|
Prawn::ManualBuilder::Example.generate(filename) do
|
12
|
-
text
|
13
|
-
text
|
11
|
+
text 'Take this example, a simple Euro sign:'
|
12
|
+
text '€', size: 32
|
14
13
|
move_down 20
|
15
14
|
|
16
|
-
text
|
17
|
-
|
15
|
+
text 'This works, because € is one of the few ' \
|
16
|
+
'non-ASCII glyphs supported in PDF built-in fonts.'
|
18
17
|
|
19
18
|
move_down 20
|
20
19
|
|
21
|
-
text
|
20
|
+
text 'For full internationalized text support, we need to use external fonts:'
|
22
21
|
move_down 20
|
23
22
|
|
24
23
|
font("#{Prawn::DATADIR}/fonts/DejaVuSans.ttf") do
|
25
|
-
text
|
26
|
-
text
|
24
|
+
text 'ὕαλον ϕαγεῖν δύναμαι· τοῦτο οὔ με βλάπτει.'
|
25
|
+
text 'There you go.'
|
27
26
|
end
|
28
27
|
end
|
@@ -1,11 +1,10 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
# Prints a list of all of the glyphs that can be rendered by Adobe's built
|
4
4
|
# in fonts, along with their character widths and WinAnsi codes. Be sure
|
5
5
|
# to pass these glyphs as UTF-8, and Prawn will transcode them for you.
|
6
|
-
|
7
|
-
|
8
|
-
%w[.. example_helper]))
|
6
|
+
|
7
|
+
require_relative '../example_helper'
|
9
8
|
|
10
9
|
filename = File.basename(__FILE__).gsub('.rb', '.pdf')
|
11
10
|
Prawn::ManualBuilder::Example.generate(filename) do
|
@@ -14,17 +13,18 @@ Prawn::ManualBuilder::Example.generate(filename) do
|
|
14
13
|
x = 0
|
15
14
|
y = bounds.top
|
16
15
|
|
17
|
-
fields = [
|
18
|
-
|
16
|
+
fields = [
|
17
|
+
[20, :right], [8, :left], [12, :center], [30, :right], [8, :left],
|
18
|
+
[0, :left]
|
19
|
+
]
|
19
20
|
|
20
|
-
font
|
21
|
+
font 'Helvetica', size: FONT_SIZE
|
21
22
|
|
22
|
-
move_down 30
|
23
|
-
text "(See next page for WinAnsi table)", :align => :center
|
24
23
|
start_new_page
|
25
24
|
|
26
25
|
Prawn::Encoding::WinAnsi::CHARACTERS.each_with_index do |name, index|
|
27
|
-
next if name ==
|
26
|
+
next if name == '.notdef'
|
27
|
+
|
28
28
|
y -= FONT_SIZE
|
29
29
|
|
30
30
|
if y < FONT_SIZE
|
@@ -32,17 +32,17 @@ Prawn::ManualBuilder::Example.generate(filename) do
|
|
32
32
|
x += 170
|
33
33
|
end
|
34
34
|
|
35
|
-
code =
|
36
|
-
char = index.chr
|
35
|
+
code = format('%<index>d.', index: index)
|
36
|
+
char = index.chr.force_encoding(::Encoding::Windows_1252)
|
37
37
|
|
38
|
-
width = 1000 * width_of(char, :
|
39
|
-
size
|
38
|
+
width = 1000 * width_of(char, size: FONT_SIZE) / FONT_SIZE
|
39
|
+
size = format('%<width>d', width: width)
|
40
40
|
|
41
41
|
data = [code, nil, char, size, nil, name]
|
42
|
-
dx
|
42
|
+
dx = x
|
43
43
|
fields.zip(data).each do |(total_width, align), field|
|
44
44
|
if field
|
45
|
-
width = width_of(field, :
|
45
|
+
width = width_of(field, size: FONT_SIZE)
|
46
46
|
|
47
47
|
case align
|
48
48
|
when :left then offset = 0
|
@@ -50,8 +50,10 @@ Prawn::ManualBuilder::Example.generate(filename) do
|
|
50
50
|
when :center then offset = (total_width - width) / 2
|
51
51
|
end
|
52
52
|
|
53
|
-
text_box(
|
54
|
-
|
53
|
+
text_box(
|
54
|
+
field.dup.force_encoding('windows-1252').encode('UTF-8'),
|
55
|
+
at: [dx + offset, y]
|
56
|
+
)
|
55
57
|
end
|
56
58
|
|
57
59
|
dx += total_width
|
data/prawn.gemspec
CHANGED
@@ -1,44 +1,56 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
basedir = __dir__
|
2
4
|
|
3
5
|
require "#{basedir}/lib/prawn/version"
|
4
6
|
|
5
7
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
8
|
+
spec.name = 'prawn'
|
7
9
|
spec.version = Prawn::VERSION
|
8
10
|
spec.platform = Gem::Platform::RUBY
|
9
|
-
spec.summary =
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
spec.
|
24
|
-
spec.
|
25
|
-
spec.
|
26
|
-
|
27
|
-
spec.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
spec.
|
32
|
-
|
33
|
-
|
34
|
-
|
11
|
+
spec.summary = 'A fast and nimble PDF generator for Ruby'
|
12
|
+
|
13
|
+
spec.cert_chain = ['certs/pointlessone.pem']
|
14
|
+
if $PROGRAM_NAME.end_with? 'gem'
|
15
|
+
spec.signing_key = File.expand_path('~/.gem/gem-private_key.pem')
|
16
|
+
end
|
17
|
+
|
18
|
+
spec.files = Dir.glob('{examples,lib,spec,manual}/**/**/*') +
|
19
|
+
Dir.glob('data/fonts/{MustRead.html,*.afm}') +
|
20
|
+
[
|
21
|
+
'Rakefile', 'prawn.gemspec', 'Gemfile',
|
22
|
+
'COPYING', 'LICENSE', 'GPLv2', 'GPLv3',
|
23
|
+
'.yardopts'
|
24
|
+
]
|
25
|
+
spec.require_path = 'lib'
|
26
|
+
spec.required_ruby_version = '~> 2.5'
|
27
|
+
spec.required_rubygems_version = '>= 1.3.6'
|
28
|
+
|
29
|
+
spec.authors = [
|
30
|
+
'Gregory Brown', 'Brad Ediger', 'Daniel Nelson', 'Jonathan Greenberg',
|
31
|
+
'James Healy'
|
32
|
+
]
|
33
|
+
spec.email = [
|
34
|
+
'gregory.t.brown@gmail.com', 'brad@bradediger.com', 'dnelson@bluejade.com',
|
35
|
+
'greenberg@entryway.net', 'jimmy@deefa.com'
|
36
|
+
]
|
37
|
+
spec.licenses = %w[PRAWN GPL-2.0 GPL-3.0]
|
38
|
+
|
39
|
+
spec.add_dependency('pdf-core', '~> 0.8.1')
|
40
|
+
spec.add_dependency('ttfunk', '~> 1.6')
|
41
|
+
|
42
|
+
spec.add_development_dependency('pdf-inspector', '>= 1.2.1', '< 2.0.a')
|
43
|
+
spec.add_development_dependency('pdf-reader', ['~> 1.4', '>= 1.4.1'])
|
44
|
+
spec.add_development_dependency('prawn-manual_builder', '>= 0.3.0')
|
45
|
+
spec.add_development_dependency('rake', '~> 12.0')
|
46
|
+
spec.add_development_dependency('rspec', '~> 3.0')
|
47
|
+
spec.add_development_dependency('rubocop', '~> 0.84.0')
|
48
|
+
spec.add_development_dependency('rubocop-performance', '~> 1.1')
|
49
|
+
spec.add_development_dependency('rubocop-rspec', '~> 1.32')
|
35
50
|
spec.add_development_dependency('simplecov')
|
36
|
-
spec.add_development_dependency('
|
37
|
-
spec.add_development_dependency('pdf-reader', '~>1.2')
|
38
|
-
spec.add_development_dependency('rubocop', '0.30.1')
|
39
|
-
spec.add_development_dependency('code_statistics', '0.2.13')
|
51
|
+
spec.add_development_dependency('yard')
|
40
52
|
|
41
|
-
spec.homepage =
|
53
|
+
spec.homepage = 'http://prawnpdf.org'
|
42
54
|
spec.description = <<END_DESC
|
43
55
|
Prawn is a fast, tiny, and nimble PDF generator for Ruby
|
44
56
|
END_DESC
|
@@ -1,11 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module EncodingHelpers
|
4
4
|
def win1252_string(str)
|
5
|
-
str.force_encoding(Encoding::Windows_1252)
|
5
|
+
str.dup.force_encoding(Encoding::Windows_1252)
|
6
6
|
end
|
7
7
|
|
8
8
|
def bin_string(str)
|
9
|
-
str.force_encoding(Encoding::ASCII_8BIT)
|
9
|
+
str.dup.force_encoding(Encoding::ASCII_8BIT)
|
10
10
|
end
|
11
11
|
end
|
@@ -0,0 +1,546 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Prawn::Document::BoundingBox do
|
6
|
+
let(:pdf) { create_pdf }
|
7
|
+
let(:x) { 100 }
|
8
|
+
let(:y) { 125 }
|
9
|
+
let(:width) { 50 }
|
10
|
+
let(:height) { 75 }
|
11
|
+
let(:box) do
|
12
|
+
described_class.new(
|
13
|
+
nil,
|
14
|
+
nil,
|
15
|
+
[x, y],
|
16
|
+
width: width,
|
17
|
+
height: height
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has an anchor at (x, y - height)' do
|
22
|
+
expect(box.anchor).to eq([x, y - height])
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'has a left boundary of 0' do
|
26
|
+
expect(box.left).to eq(0)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'has a right boundary equal to the width' do
|
30
|
+
expect(box.right).to eq(width)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'has a top boundary of height' do
|
34
|
+
expect(box.top).to eq(height)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'has a bottom boundary of 0' do
|
38
|
+
expect(box.bottom).to eq(0)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'has a top-left of [0,height]' do
|
42
|
+
expect(box.top_left).to eq([0, height])
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'has a top-right of [width,height]' do
|
46
|
+
expect(box.top_right).to eq([width, height])
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'has a bottom-left of [0,0]' do
|
50
|
+
expect(box.bottom_left).to eq([0, 0])
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'has a bottom-right of [width,0]' do
|
54
|
+
expect(box.bottom_right).to eq([width, 0])
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'has an absolute left boundary of x' do
|
58
|
+
expect(box.absolute_left).to eq(x)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'has an absolute right boundary of x + width' do
|
62
|
+
expect(box.absolute_right).to eq(x + width)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'has an absolute top boundary of y' do
|
66
|
+
expect(box.absolute_top).to eq(y)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'has an absolute bottom boundary of y - height' do
|
70
|
+
expect(box.absolute_bottom).to eq(y - height)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'has an absolute bottom-left of [x,y-height]' do
|
74
|
+
expect(box.absolute_bottom_left).to eq([x, y - height])
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'has an absolute bottom-right of [x+width,y-height]' do
|
78
|
+
expect(box.absolute_bottom_right).to eq([x + width, y - height])
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'has an absolute top-left of [x,y]' do
|
82
|
+
expect(box.absolute_top_left).to eq([x, y])
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'has an absolute top-right of [x+width,y]' do
|
86
|
+
expect(box.absolute_top_right).to eq([x + width, y])
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'requires width to be set' do
|
90
|
+
expect do
|
91
|
+
described_class.new(nil, nil, [100, 100])
|
92
|
+
end.to raise_error(ArgumentError)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'raise_errors an ArgumentError if a block is not passed' do
|
96
|
+
pdf = Prawn::Document.new
|
97
|
+
expect do
|
98
|
+
pdf.bounding_box([0, 0], width: 200)
|
99
|
+
end.to raise_error(ArgumentError)
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'drawing' do
|
103
|
+
it 'does not stomp on the arguments to bounding_box' do
|
104
|
+
pdf = Prawn::Document.new
|
105
|
+
x = [100, 500]
|
106
|
+
pdf.bounding_box x, width: 100 do
|
107
|
+
pdf.text 'bork-bork-bork'
|
108
|
+
end
|
109
|
+
expect(x).to eq([100, 500])
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'restores Document#bounds to the correct margin box on exit' do
|
113
|
+
pdf = Prawn::Document.new(margin: 200)
|
114
|
+
|
115
|
+
# add a multi-page bounding box
|
116
|
+
pdf.bounding_box([100, pdf.bounds.top], width: 400) do
|
117
|
+
pdf.text "The rain in spain falls mainly in the plains.\n" * 30
|
118
|
+
end
|
119
|
+
|
120
|
+
pdf.start_new_page(margin: 0)
|
121
|
+
|
122
|
+
x_min, y_min, x_max, y_max = pdf.page.dimensions
|
123
|
+
|
124
|
+
expect(pdf.bounds.absolute_top_left).to eq([x_min, y_max])
|
125
|
+
expect(pdf.bounds.absolute_bottom_right).to eq([x_max, y_min])
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'restores the parent bounding box when calls are nested' do
|
129
|
+
pdf.bounding_box [100, 500], width: 300, height: 300 do
|
130
|
+
expect(pdf.bounds.absolute_top)
|
131
|
+
.to eq(500 + pdf.margin_box.absolute_bottom)
|
132
|
+
expect(pdf.bounds.absolute_left)
|
133
|
+
.to eq(100 + pdf.margin_box.absolute_left)
|
134
|
+
|
135
|
+
parent_box = pdf.bounds
|
136
|
+
|
137
|
+
pdf.bounding_box [50, 200], width: 100, height: 100 do
|
138
|
+
expect(pdf.bounds.absolute_top)
|
139
|
+
.to eq(200 + parent_box.absolute_bottom)
|
140
|
+
expect(pdf.bounds.absolute_left).to eq(50 + parent_box.absolute_left)
|
141
|
+
end
|
142
|
+
|
143
|
+
expect(pdf.bounds.absolute_top)
|
144
|
+
.to eq(500 + pdf.margin_box.absolute_bottom)
|
145
|
+
expect(pdf.bounds.absolute_left)
|
146
|
+
.to eq(100 + pdf.margin_box.absolute_left)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'calculates a height if none is specified' do
|
151
|
+
pdf.bounding_box([100, 500], width: 100) do
|
152
|
+
pdf.text 'The rain in Spain falls mainly on the plains.'
|
153
|
+
end
|
154
|
+
|
155
|
+
expect(pdf.y).to be_within(0.001).of(458.384)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'keeps track of the max height the box was stretched to' do
|
159
|
+
box = pdf.bounding_box(pdf.bounds.top_left, width: 100) do
|
160
|
+
pdf.move_down 100
|
161
|
+
pdf.move_up 15
|
162
|
+
end
|
163
|
+
|
164
|
+
expect(box.height).to eq(100)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'advances the y-position by bbox.height by default' do
|
168
|
+
orig_y = pdf.y
|
169
|
+
pdf.bounding_box [0, pdf.cursor], width: pdf.bounds.width, height: 30 do
|
170
|
+
pdf.text 'hello'
|
171
|
+
end
|
172
|
+
expect(pdf.y).to be_within(0.001).of(orig_y - 30)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'does not advance y-position if passed :hold_position => true' do
|
176
|
+
orig_y = pdf.y
|
177
|
+
pdf.bounding_box(
|
178
|
+
[0, pdf.cursor],
|
179
|
+
width: pdf.bounds.width,
|
180
|
+
hold_position: true
|
181
|
+
) do
|
182
|
+
pdf.text 'hello'
|
183
|
+
end
|
184
|
+
# y only advances by height of one line ("hello")
|
185
|
+
expect(pdf.y).to be_within(0.001).of(orig_y - pdf.height_of('hello'))
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'does not advance y-position of a stretchy bbox if it would stretch '\
|
189
|
+
'the bbox further' do
|
190
|
+
bottom = pdf.y = pdf.margin_box.absolute_bottom
|
191
|
+
pdf.bounding_box [0, pdf.margin_box.top], width: pdf.bounds.width do
|
192
|
+
pdf.y = bottom
|
193
|
+
pdf.text 'hello' # starts a new page
|
194
|
+
end
|
195
|
+
expect(pdf.page_count).to eq(2)
|
196
|
+
|
197
|
+
# Restoring the position (to the absolute bottom) would stretch the bbox
|
198
|
+
# to the bottom of the page, which we don't want. This should be
|
199
|
+
# equivalent to a bbox with :hold_position => true, where we only advance
|
200
|
+
# by the amount that was actually drawn.
|
201
|
+
expect(pdf.y).to be_within(0.001).of(
|
202
|
+
pdf.margin_box.absolute_top - pdf.height_of('hello')
|
203
|
+
)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe 'Indentation' do
|
208
|
+
it 'temporarilies shift the x coordinate and width' do
|
209
|
+
pdf.bounding_box([100, 100], width: 200) do
|
210
|
+
pdf.indent(20) do
|
211
|
+
expect(pdf.bounds.absolute_left).to eq(120)
|
212
|
+
expect(pdf.bounds.width).to eq(180)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'restores the x coordinate and width after block exits' do
|
218
|
+
pdf.bounding_box([100, 100], width: 200) do
|
219
|
+
pdf.indent(20) do
|
220
|
+
# no-op
|
221
|
+
end
|
222
|
+
expect(pdf.bounds.absolute_left).to eq(100)
|
223
|
+
expect(pdf.bounds.width).to eq(200)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'restores the x coordinate and width on error' do
|
228
|
+
pdf.bounding_box([100, 100], width: 200) do
|
229
|
+
pdf.indent(20) { raise }
|
230
|
+
rescue StandardError
|
231
|
+
expect(pdf.bounds.absolute_left).to eq(100)
|
232
|
+
expect(pdf.bounds.width).to eq(200)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'maintains left indentation across a page break' do
|
237
|
+
original_left = pdf.bounds.absolute_left
|
238
|
+
|
239
|
+
pdf.indent(20) do
|
240
|
+
expect(pdf.bounds.absolute_left).to eq(original_left + 20)
|
241
|
+
pdf.start_new_page
|
242
|
+
expect(pdf.bounds.absolute_left).to eq(original_left + 20)
|
243
|
+
end
|
244
|
+
|
245
|
+
expect(pdf.bounds.absolute_left).to eq(original_left)
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'maintains right indentation across a page break' do
|
249
|
+
original_width = pdf.bounds.width
|
250
|
+
|
251
|
+
pdf.indent(0, 20) do
|
252
|
+
expect(pdf.bounds.width).to eq(original_width - 20)
|
253
|
+
pdf.start_new_page
|
254
|
+
expect(pdf.bounds.width).to eq(original_width - 20)
|
255
|
+
end
|
256
|
+
|
257
|
+
expect(pdf.bounds.width).to eq(original_width)
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'optionally allows adjustment of the right bound as well' do
|
261
|
+
pdf.bounding_box([100, 100], width: 200) do
|
262
|
+
pdf.indent(20, 30) do
|
263
|
+
expect(pdf.bounds.absolute_left).to eq(120)
|
264
|
+
expect(pdf.bounds.width).to eq(150)
|
265
|
+
end
|
266
|
+
expect(pdf.bounds.absolute_left).to eq(100)
|
267
|
+
expect(pdf.bounds.width).to eq(200)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
describe 'in a ColumnBox' do
|
272
|
+
it 'subtracts the given indentation from the available width' do
|
273
|
+
pdf.column_box(
|
274
|
+
[0, pdf.cursor],
|
275
|
+
width: pdf.bounds.width,
|
276
|
+
height: 200,
|
277
|
+
columns: 2,
|
278
|
+
spacer: 20
|
279
|
+
) do
|
280
|
+
width = pdf.bounds.width
|
281
|
+
pdf.indent(20) do
|
282
|
+
expect(pdf.bounds.width).to be_within(0.01).of(width - 20)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'subtracts right padding from the available width' do
|
288
|
+
pdf.column_box(
|
289
|
+
[0, pdf.cursor],
|
290
|
+
width: pdf.bounds.width,
|
291
|
+
height: 200,
|
292
|
+
columns: 2,
|
293
|
+
spacer: 20
|
294
|
+
) do
|
295
|
+
width = pdf.bounds.width
|
296
|
+
pdf.indent(20, 30) do
|
297
|
+
expect(pdf.bounds.width).to be_within(0.01).of(width - 50)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'maintains the same left indentation across column breaks' do
|
303
|
+
pdf.column_box(
|
304
|
+
[0, pdf.cursor],
|
305
|
+
width: pdf.bounds.width,
|
306
|
+
columns: 3,
|
307
|
+
spacer: 15
|
308
|
+
) do
|
309
|
+
3.times do |_column|
|
310
|
+
x = pdf.bounds.left_side
|
311
|
+
pdf.indent(20) do
|
312
|
+
expect(pdf.bounds.left_side).to eq(x + 20)
|
313
|
+
end
|
314
|
+
pdf.bounds.move_past_bottom
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'does not change the right margin if only left indentation is '\
|
320
|
+
'requested' do
|
321
|
+
pdf.column_box(
|
322
|
+
[0, pdf.cursor],
|
323
|
+
width: pdf.bounds.width,
|
324
|
+
columns: 3,
|
325
|
+
spacer: 15
|
326
|
+
) do
|
327
|
+
3.times do |_column|
|
328
|
+
x = pdf.bounds.right_side
|
329
|
+
pdf.indent(20) do
|
330
|
+
expect(pdf.bounds.right_side).to eq(x)
|
331
|
+
end
|
332
|
+
pdf.bounds.move_past_bottom
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
it 'maintains the same right indentation across columns' do
|
338
|
+
pdf.column_box(
|
339
|
+
[0, pdf.cursor],
|
340
|
+
width: pdf.bounds.width,
|
341
|
+
columns: 3,
|
342
|
+
spacer: 15
|
343
|
+
) do
|
344
|
+
3.times do |_column|
|
345
|
+
x = pdf.bounds.right_side
|
346
|
+
pdf.indent(20, 10) do
|
347
|
+
expect(pdf.bounds.right_side).to eq(x - 10)
|
348
|
+
end
|
349
|
+
pdf.bounds.move_past_bottom
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
it 'keeps the right indentation after nesting indents' do
|
355
|
+
pdf.column_box(
|
356
|
+
[0, pdf.cursor],
|
357
|
+
width: pdf.bounds.width,
|
358
|
+
columns: 3,
|
359
|
+
spacer: 15
|
360
|
+
) do
|
361
|
+
3.times do |_column|
|
362
|
+
# I am giving a right indent of 10...
|
363
|
+
pdf.indent(20, 10) do
|
364
|
+
x = pdf.bounds.right_side
|
365
|
+
# ...and no right indent here...
|
366
|
+
pdf.indent(20) do
|
367
|
+
# right indent is inherited from the parent!
|
368
|
+
expect(pdf.bounds.right_side).to eq(x)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
pdf.bounds.move_past_bottom
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
it 'reverts the right indentation if negative indent is given in '\
|
377
|
+
'nested indent' do
|
378
|
+
pdf.column_box(
|
379
|
+
[0, pdf.cursor],
|
380
|
+
width: pdf.bounds.width,
|
381
|
+
columns: 3,
|
382
|
+
spacer: 15
|
383
|
+
) do
|
384
|
+
3.times do |_column|
|
385
|
+
x = pdf.bounds.right_side
|
386
|
+
pdf.indent(20, 10) do
|
387
|
+
# requesting a negative right-indent of equivalent size...
|
388
|
+
pdf.indent(20, -10) do
|
389
|
+
# ...resets the right margin to that of the column!
|
390
|
+
expect(pdf.bounds.right_side).to eq(x)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
pdf.bounds.move_past_bottom
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
it 'reduces the available column width by the sum of ' \
|
399
|
+
'all nested indents' do
|
400
|
+
pdf.column_box(
|
401
|
+
[0, pdf.cursor],
|
402
|
+
width: pdf.bounds.width,
|
403
|
+
columns: 3,
|
404
|
+
spacer: 15
|
405
|
+
) do
|
406
|
+
3.times do |_column|
|
407
|
+
w = pdf.bounds.width
|
408
|
+
pdf.indent(20, 10) do
|
409
|
+
pdf.indent(20, 10) do
|
410
|
+
expect(pdf.bounds.width).to eq(w - 60)
|
411
|
+
end
|
412
|
+
end
|
413
|
+
pdf.bounds.move_past_bottom
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
describe 'A canvas' do
|
421
|
+
it 'uses whatever the last set y position is' do
|
422
|
+
pdf.canvas do
|
423
|
+
pdf.bounding_box([100, 500], width: 200) { pdf.move_down 50 }
|
424
|
+
end
|
425
|
+
expect(pdf.y).to eq(450)
|
426
|
+
end
|
427
|
+
|
428
|
+
it 'restores the original ypos after execution', issue: 523 do
|
429
|
+
doc = Prawn::Document.new(skip_page_creation: true)
|
430
|
+
doc.start_new_page
|
431
|
+
|
432
|
+
original_ypos = doc.y
|
433
|
+
|
434
|
+
doc.canvas {}
|
435
|
+
|
436
|
+
expect(doc.y).to eq(original_ypos)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
describe 'Deep-copying' do
|
441
|
+
it 'creates a new object that does not copy @document' do
|
442
|
+
Prawn::Document.new do |pdf|
|
443
|
+
orig = pdf.bounds
|
444
|
+
copy = orig.deep_copy
|
445
|
+
|
446
|
+
expect(copy).to_not eq(pdf.bounds)
|
447
|
+
expect(copy.document).to be_nil
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
it 'deep-copies parent bounds' do
|
452
|
+
Prawn::Document.new do |pdf|
|
453
|
+
outside = pdf.bounds
|
454
|
+
pdf.bounding_box [100, 100], width: 100 do
|
455
|
+
copy = pdf.bounds.deep_copy
|
456
|
+
|
457
|
+
# the parent bounds should have the same parameters
|
458
|
+
expect(copy.parent.width).to eq(outside.width)
|
459
|
+
expect(copy.parent.height).to eq(outside.height)
|
460
|
+
|
461
|
+
# but should not be the same object
|
462
|
+
expect(copy.parent).to_not eq(outside)
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
describe 'Prawn::Document#reference_bounds' do
|
469
|
+
it 'returns self for non-stretchy bounds' do
|
470
|
+
pdf.bounding_box([0, pdf.cursor], width: 100, height: 100) do
|
471
|
+
expect(pdf.reference_bounds).to eq(pdf.bounds)
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
it 'returns the parent bounds if in a stretchy box' do
|
476
|
+
pdf.bounding_box([0, pdf.cursor], width: 100, height: 100) do
|
477
|
+
correct_bounds = pdf.bounds
|
478
|
+
pdf.bounding_box([0, pdf.cursor], width: 100) do
|
479
|
+
expect(pdf.reference_bounds).to eq(correct_bounds)
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
it 'finds the non-stretchy box through 2 levels' do
|
485
|
+
pdf.bounding_box([0, pdf.cursor], width: 100, height: 100) do
|
486
|
+
correct_bounds = pdf.bounds
|
487
|
+
pdf.bounding_box([0, pdf.cursor], width: 100) do
|
488
|
+
pdf.bounding_box([0, pdf.cursor], width: 100) do
|
489
|
+
expect(pdf.reference_bounds).to eq(correct_bounds)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
it "returns the margin box if there's no explicit bbox" do
|
496
|
+
expect(pdf.reference_bounds).to eq(pdf.margin_box)
|
497
|
+
|
498
|
+
pdf.bounding_box([0, pdf.cursor], width: 100) do
|
499
|
+
expect(pdf.reference_bounds).to eq(pdf.margin_box)
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
it "returns the canvas box if we're in a canvas" do
|
504
|
+
pdf.canvas do
|
505
|
+
canvas_box = pdf.bounds
|
506
|
+
|
507
|
+
expect(pdf.reference_bounds).to eq(canvas_box)
|
508
|
+
|
509
|
+
pdf.bounding_box([0, pdf.cursor], width: 100) do
|
510
|
+
expect(pdf.reference_bounds).to eq(canvas_box)
|
511
|
+
end
|
512
|
+
end
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
describe '#move_past_bottom' do
|
517
|
+
it 'ordinarilies start a new page' do
|
518
|
+
pdf.bounds.move_past_bottom
|
519
|
+
pdf.text 'Foo'
|
520
|
+
|
521
|
+
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
522
|
+
expect(pages.size).to eq(2)
|
523
|
+
expect(pages[0][:strings]).to eq([])
|
524
|
+
expect(pages[1][:strings]).to eq(['Foo'])
|
525
|
+
end
|
526
|
+
|
527
|
+
it 'moves to the top of the next page if it exists already' do
|
528
|
+
# save away the y-position at the top of a page
|
529
|
+
top_y = pdf.y
|
530
|
+
|
531
|
+
# create a blank page but go to the page before it
|
532
|
+
pdf.start_new_page
|
533
|
+
pdf.go_to_page 1
|
534
|
+
pdf.text 'Foo'
|
535
|
+
|
536
|
+
pdf.bounds.move_past_bottom
|
537
|
+
expect(pdf.y).to be_within(0.001).of(top_y)
|
538
|
+
pdf.text 'Bar'
|
539
|
+
|
540
|
+
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
541
|
+
expect(pages.size).to eq(2)
|
542
|
+
expect(pages[0][:strings]).to eq(['Foo'])
|
543
|
+
expect(pages[1][:strings]).to eq(['Bar'])
|
544
|
+
end
|
545
|
+
end
|
546
|
+
end
|