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/document.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# document.rb : Implements PDF document generation for Prawn
|
4
4
|
#
|
@@ -6,23 +6,21 @@
|
|
6
6
|
#
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
|
9
|
-
require
|
9
|
+
require 'stringio'
|
10
10
|
|
11
|
-
require_relative
|
12
|
-
require_relative
|
13
|
-
require_relative
|
14
|
-
require_relative
|
15
|
-
require_relative "document/graphics_state"
|
11
|
+
require_relative 'document/bounding_box'
|
12
|
+
require_relative 'document/column_box'
|
13
|
+
require_relative 'document/internals'
|
14
|
+
require_relative 'document/span'
|
16
15
|
|
17
16
|
module Prawn
|
18
|
-
|
19
17
|
# The Prawn::Document class is how you start creating a PDF document.
|
20
18
|
#
|
21
19
|
# There are three basic ways you can instantiate PDF Documents in Prawn, they
|
22
|
-
# are through assignment, implicit block or explicit block. Below is an
|
23
|
-
# of each type, each example does exactly the same thing, makes a PDF
|
24
|
-
# with all the defaults and puts in the default font "Hello There"
|
25
|
-
# saves it to the current directory as "example.pdf"
|
20
|
+
# are through assignment, implicit block or explicit block. Below is an
|
21
|
+
# example of each type, each example does exactly the same thing, makes a PDF
|
22
|
+
# document with all the defaults and puts in the default font "Hello There"
|
23
|
+
# and then saves it to the current directory as "example.pdf"
|
26
24
|
#
|
27
25
|
# For example, assignment can be like this:
|
28
26
|
#
|
@@ -44,8 +42,8 @@ module Prawn
|
|
44
42
|
# pdf.text words
|
45
43
|
# end
|
46
44
|
#
|
47
|
-
# Usually, the block forms are used when you are simply creating a PDF
|
48
|
-
# that you want to immediately save or render out.
|
45
|
+
# Usually, the block forms are used when you are simply creating a PDF
|
46
|
+
# document that you want to immediately save or render out.
|
49
47
|
#
|
50
48
|
# See the new and generate methods for further details on the above.
|
51
49
|
#
|
@@ -53,23 +51,25 @@ module Prawn
|
|
53
51
|
include Prawn::Document::Internals
|
54
52
|
include PDF::Core::Annotations
|
55
53
|
include PDF::Core::Destinations
|
56
|
-
include Prawn::Document::GraphicsState
|
57
54
|
include Prawn::Document::Security
|
58
55
|
include Prawn::Text
|
59
56
|
include Prawn::Graphics
|
60
57
|
include Prawn::Images
|
61
58
|
include Prawn::Stamp
|
62
59
|
include Prawn::SoftMask
|
60
|
+
include Prawn::TransformationStack
|
63
61
|
|
64
62
|
# @group Extension API
|
65
63
|
|
66
64
|
# NOTE: We probably need to rethink the options validation system, but this
|
67
65
|
# constant temporarily allows for extensions to modify the list.
|
68
66
|
|
69
|
-
VALID_OPTIONS = [
|
70
|
-
|
71
|
-
|
72
|
-
|
67
|
+
VALID_OPTIONS = %i[
|
68
|
+
page_size page_layout margin left_margin
|
69
|
+
right_margin top_margin bottom_margin skip_page_creation
|
70
|
+
compress background info
|
71
|
+
text_formatter print_scaling
|
72
|
+
].freeze
|
73
73
|
|
74
74
|
# Any module added to this array will be included into instances of
|
75
75
|
# Prawn::Document at the per-object level. These will also be inherited by
|
@@ -98,13 +98,14 @@ module Prawn
|
|
98
98
|
|
99
99
|
# @private
|
100
100
|
def self.inherited(base)
|
101
|
+
super
|
101
102
|
extensions.each { |e| base.extensions << e }
|
102
103
|
end
|
103
104
|
|
104
105
|
# @group Stable Attributes
|
105
106
|
|
106
107
|
attr_accessor :margin_box
|
107
|
-
attr_reader
|
108
|
+
attr_reader :margins, :y
|
108
109
|
attr_accessor :page_number
|
109
110
|
|
110
111
|
# @group Extension Attributes
|
@@ -140,8 +141,8 @@ module Prawn
|
|
140
141
|
# pdf.draw_text content, :at => [200,720], :size => 32
|
141
142
|
# end
|
142
143
|
#
|
143
|
-
def self.generate(filename,options={}
|
144
|
-
pdf = new(options
|
144
|
+
def self.generate(filename, options = {}, &block)
|
145
|
+
pdf = new(options, &block)
|
145
146
|
pdf.render_file(filename)
|
146
147
|
end
|
147
148
|
|
@@ -155,15 +156,22 @@ module Prawn
|
|
155
156
|
# <tt>:right_margin</tt>:: Sets the right margin in points [0.5 inch]
|
156
157
|
# <tt>:top_margin</tt>:: Sets the top margin in points [0.5 inch]
|
157
158
|
# <tt>:bottom_margin</tt>:: Sets the bottom margin in points [0.5 inch]
|
158
|
-
# <tt>:skip_page_creation</tt>:: Creates a document without starting the
|
159
|
-
#
|
160
|
-
# <tt>:
|
159
|
+
# <tt>:skip_page_creation</tt>:: Creates a document without starting the
|
160
|
+
# first page [false]
|
161
|
+
# <tt>:compress</tt>:: Compresses content streams before rendering them
|
162
|
+
# [false]
|
163
|
+
# <tt>:background</tt>:: An image path to be used as background on all pages
|
164
|
+
# [nil]
|
161
165
|
# <tt>:background_scale</tt>:: Backgound image scale [1] [nil]
|
162
|
-
# <tt>:info</tt>:: Generic hash allowing for custom metadata properties
|
163
|
-
#
|
166
|
+
# <tt>:info</tt>:: Generic hash allowing for custom metadata properties
|
167
|
+
# [nil]
|
168
|
+
# <tt>:text_formatter</tt>: The text formatter to use for
|
169
|
+
# <tt>:inline_format</tt>ted text
|
170
|
+
# [Prawn::Text::Formatted::Parser]
|
164
171
|
#
|
165
|
-
# Setting e.g. the :margin to 100 points and the :left_margin to 50 will
|
166
|
-
# of 100 points on every side except for the left, where
|
172
|
+
# Setting e.g. the :margin to 100 points and the :left_margin to 50 will
|
173
|
+
# result in margins of 100 points on every side except for the left, where
|
174
|
+
# it will be 50.
|
167
175
|
#
|
168
176
|
# The :margin can also be an array much like CSS shorthand:
|
169
177
|
#
|
@@ -174,8 +182,8 @@ module Prawn
|
|
174
182
|
# # Top is 10, right is 20, bottom is 30, left is 40.
|
175
183
|
# :margin => [10, 20, 30, 40]
|
176
184
|
#
|
177
|
-
# Additionally, :page_size can be specified as a simple two value array
|
178
|
-
# the width and height of the document you need in PDF Points.
|
185
|
+
# Additionally, :page_size can be specified as a simple two value array
|
186
|
+
# giving the width and height of the document you need in PDF Points.
|
179
187
|
#
|
180
188
|
# Usage:
|
181
189
|
#
|
@@ -183,15 +191,17 @@ module Prawn
|
|
183
191
|
# pdf = Prawn::Document.new
|
184
192
|
#
|
185
193
|
# # New document, A4 paper, landscaped
|
186
|
-
# pdf = Prawn::Document.new(:
|
194
|
+
# pdf = Prawn::Document.new(page_size: "A4", page_layout: :landscape)
|
187
195
|
#
|
188
196
|
# # New document, Custom size
|
189
|
-
# pdf = Prawn::Document.new(:
|
197
|
+
# pdf = Prawn::Document.new(page_size: [200, 300])
|
190
198
|
#
|
191
199
|
# # New document, with background
|
192
|
-
# pdf = Prawn::Document.new(
|
200
|
+
# pdf = Prawn::Document.new(
|
201
|
+
# background: "#{Prawn::DATADIR}/images/pigs.jpg"
|
202
|
+
# )
|
193
203
|
#
|
194
|
-
def initialize(options={}
|
204
|
+
def initialize(options = {}, &block)
|
195
205
|
options = options.dup
|
196
206
|
|
197
207
|
Prawn.verify_options VALID_OPTIONS, options
|
@@ -200,22 +210,23 @@ module Prawn
|
|
200
210
|
# raise NotImplementedError if options[:skip_page_creation]
|
201
211
|
|
202
212
|
self.class.extensions.reverse_each { |e| extend e }
|
203
|
-
|
204
|
-
|
205
|
-
min_version(state.store.min_version) if state.store.min_version
|
213
|
+
self.state = PDF::Core::DocumentState.new(options)
|
214
|
+
state.populate_pages_from_store(self)
|
215
|
+
renderer.min_version(state.store.min_version) if state.store.min_version
|
206
216
|
|
207
|
-
min_version(1.6) if options[:print_scaling] == :none
|
217
|
+
renderer.min_version(1.6) if options[:print_scaling] == :none
|
208
218
|
|
209
219
|
@background = options[:background]
|
210
220
|
@background_scale = options[:background_scale] || 1
|
211
|
-
@font_size
|
221
|
+
@font_size = 12
|
212
222
|
|
213
|
-
@bounding_box
|
214
|
-
@margin_box
|
223
|
+
@bounding_box = nil
|
224
|
+
@margin_box = nil
|
215
225
|
|
216
226
|
@page_number = 0
|
217
227
|
|
218
|
-
@text_formatter = options.delete(:text_formatter) ||
|
228
|
+
@text_formatter = options.delete(:text_formatter) ||
|
229
|
+
Text::Formatted::Parser
|
219
230
|
|
220
231
|
options[:size] = options.delete(:page_size)
|
221
232
|
options[:layout] = options.delete(:page_layout)
|
@@ -242,20 +253,28 @@ module Prawn
|
|
242
253
|
# pdf.start_new_page(:margin => 100)
|
243
254
|
#
|
244
255
|
def start_new_page(options = {})
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
256
|
+
last_page = state.page
|
257
|
+
if last_page
|
258
|
+
last_page_size = last_page.size
|
259
|
+
last_page_layout = last_page.layout
|
260
|
+
last_page_margins = last_page.margins.dup
|
249
261
|
end
|
250
262
|
|
251
|
-
page_options = {
|
252
|
-
|
253
|
-
|
263
|
+
page_options = {
|
264
|
+
size: options[:size] || last_page_size,
|
265
|
+
layout: options[:layout] || last_page_layout,
|
266
|
+
margins: last_page_margins
|
267
|
+
}
|
254
268
|
if last_page
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
269
|
+
if last_page.graphic_state
|
270
|
+
new_graphic_state = last_page.graphic_state.dup
|
271
|
+
end
|
272
|
+
|
273
|
+
# erase the color space so that it gets reset on new page for fussy
|
274
|
+
# pdf-readers
|
275
|
+
new_graphic_state&.color_space = {}
|
276
|
+
|
277
|
+
page_options[:graphic_state] = new_graphic_state
|
259
278
|
end
|
260
279
|
|
261
280
|
state.page = PDF::Core::Page.new(self, page_options)
|
@@ -275,7 +294,11 @@ module Prawn
|
|
275
294
|
state.insert_page(state.page, @page_number)
|
276
295
|
@page_number += 1
|
277
296
|
|
278
|
-
|
297
|
+
if @background
|
298
|
+
canvas do
|
299
|
+
image(@background, scale: @background_scale, at: bounds.top_left)
|
300
|
+
end
|
301
|
+
end
|
279
302
|
@y = @bounding_box.absolute_top
|
280
303
|
|
281
304
|
float do
|
@@ -284,6 +307,26 @@ module Prawn
|
|
284
307
|
end
|
285
308
|
end
|
286
309
|
|
310
|
+
# Remove page of the document by index
|
311
|
+
#
|
312
|
+
# pdf = Prawn::Document.new
|
313
|
+
# pdf.page_count #=> 1
|
314
|
+
# 3.times { pdf.start_new_page }
|
315
|
+
# pdf.page_count #=> 4
|
316
|
+
# pdf.delete_page(-1)
|
317
|
+
# pdf.page_count #=> 3
|
318
|
+
#
|
319
|
+
def delete_page(index)
|
320
|
+
return false if index.abs > (state.pages.count - 1)
|
321
|
+
|
322
|
+
state.pages.delete_at(index)
|
323
|
+
|
324
|
+
state.store.pages.data[:Kids].delete_at(index)
|
325
|
+
state.store.pages.data[:Count] -= 1
|
326
|
+
@page_number -= 1
|
327
|
+
true
|
328
|
+
end
|
329
|
+
|
287
330
|
# Returns the number of pages in the document
|
288
331
|
#
|
289
332
|
# pdf = Prawn::Document.new
|
@@ -300,9 +343,9 @@ module Prawn
|
|
300
343
|
#
|
301
344
|
# See Prawn::Document#number_pages for a sample usage of this capability.
|
302
345
|
#
|
303
|
-
def go_to_page(
|
304
|
-
@page_number =
|
305
|
-
state.page = state.pages[
|
346
|
+
def go_to_page(page_number)
|
347
|
+
@page_number = page_number
|
348
|
+
state.page = state.pages[page_number - 1]
|
306
349
|
generate_margin_box
|
307
350
|
@y = @bounding_box.absolute_top
|
308
351
|
end
|
@@ -349,23 +392,13 @@ module Prawn
|
|
349
392
|
# Renders the PDF document to string.
|
350
393
|
# Pass an open file descriptor to render to file.
|
351
394
|
#
|
352
|
-
def render(
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
finalize_all_page_contents
|
357
|
-
|
358
|
-
render_header(output)
|
359
|
-
render_body(output)
|
360
|
-
render_xref(output)
|
361
|
-
render_trailer(output)
|
362
|
-
if output.instance_of?(StringIO)
|
363
|
-
str = output.string
|
364
|
-
str.force_encoding(::Encoding::ASCII_8BIT)
|
365
|
-
return str
|
366
|
-
else
|
367
|
-
return nil
|
395
|
+
def render(*arguments, &block)
|
396
|
+
(1..page_count).each do |i|
|
397
|
+
go_to_page i
|
398
|
+
repeaters.each { |r| r.run(i) }
|
368
399
|
end
|
400
|
+
|
401
|
+
renderer.render(*arguments, &block)
|
369
402
|
end
|
370
403
|
|
371
404
|
# Renders the PDF document to file.
|
@@ -373,7 +406,7 @@ module Prawn
|
|
373
406
|
# pdf.render_file "foo.pdf"
|
374
407
|
#
|
375
408
|
def render_file(filename)
|
376
|
-
File.open(filename,
|
409
|
+
File.open(filename, 'wb') { |f| render(f) }
|
377
410
|
end
|
378
411
|
|
379
412
|
# The bounds method returns the current bounding box you are currently in,
|
@@ -382,14 +415,15 @@ module Prawn
|
|
382
415
|
# block, the box defined by that call will be returned instead of the
|
383
416
|
# document margin box.
|
384
417
|
#
|
385
|
-
# Another important point about bounding boxes is that all x and
|
386
|
-
# within a bounding box code block are relative to the bottom
|
387
|
-
# bounding box.
|
418
|
+
# Another important point about bounding boxes is that all x and
|
419
|
+
# y measurements within a bounding box code block are relative to the bottom
|
420
|
+
# left corner of the bounding box.
|
388
421
|
#
|
389
422
|
# For example:
|
390
423
|
#
|
391
424
|
# Prawn::Document.new do
|
392
|
-
# # In the default "margin box" of a Prawn document of 0.5in along each
|
425
|
+
# # In the default "margin box" of a Prawn document of 0.5in along each
|
426
|
+
# # edge
|
393
427
|
#
|
394
428
|
# # Draw a border around the page (the manual way)
|
395
429
|
# stroke do
|
@@ -416,8 +450,8 @@ module Prawn
|
|
416
450
|
|
417
451
|
# Sets Document#bounds to the BoundingBox provided. See above for a brief
|
418
452
|
# description of what a bounding box is. This function is useful if you
|
419
|
-
# really need to change the bounding box manually, but usually, just
|
420
|
-
# and exiting bounding box code blocks is good enough.
|
453
|
+
# really need to change the bounding box manually, but usually, just
|
454
|
+
# entering and exiting bounding box code blocks is good enough.
|
421
455
|
#
|
422
456
|
def bounds=(bounding_box)
|
423
457
|
@bounding_box = bounding_box
|
@@ -426,15 +460,15 @@ module Prawn
|
|
426
460
|
# Moves up the document by n points relative to the current position inside
|
427
461
|
# the current bounding box.
|
428
462
|
#
|
429
|
-
def move_up(
|
430
|
-
self.y +=
|
463
|
+
def move_up(amount)
|
464
|
+
self.y += amount
|
431
465
|
end
|
432
466
|
|
433
|
-
# Moves down the document by n points relative to the current position
|
434
|
-
# the current bounding box.
|
467
|
+
# Moves down the document by n points relative to the current position
|
468
|
+
# inside the current bounding box.
|
435
469
|
#
|
436
|
-
def move_down(
|
437
|
-
self.y -=
|
470
|
+
def move_down(amount)
|
471
|
+
self.y -= amount
|
438
472
|
end
|
439
473
|
|
440
474
|
# Moves down the document and then executes a block.
|
@@ -478,7 +512,6 @@ module Prawn
|
|
478
512
|
move_down(y)
|
479
513
|
end
|
480
514
|
|
481
|
-
|
482
515
|
# Indents the specified number of PDF points for the duration of the block
|
483
516
|
#
|
484
517
|
# pdf.text "some text"
|
@@ -495,85 +528,88 @@ module Prawn
|
|
495
528
|
bounds.indent(left, right, &block)
|
496
529
|
end
|
497
530
|
|
498
|
-
# Places a text box on specified pages for page numbering. This should be
|
499
|
-
# towards the end of document creation, after all your content is
|
500
|
-
# place. In your template string, <page> refers to the current
|
501
|
-
# <total> refers to the total amount of pages in the document.
|
502
|
-
# occur at the end of your Prawn::Document.generate
|
503
|
-
# through existing pages after they are
|
531
|
+
# Places a text box on specified pages for page numbering. This should be
|
532
|
+
# called towards the end of document creation, after all your content is
|
533
|
+
# already in place. In your template string, <page> refers to the current
|
534
|
+
# page, and <total> refers to the total amount of pages in the document.
|
535
|
+
# Page numbering should occur at the end of your Prawn::Document.generate
|
536
|
+
# block because the method iterates through existing pages after they are
|
537
|
+
# created.
|
504
538
|
#
|
505
539
|
# Parameters are:
|
506
540
|
#
|
507
541
|
# <tt>string</tt>:: Template string for page number wording.
|
508
542
|
# Should include '<page>' and, optionally, '<total>'.
|
509
543
|
# <tt>options</tt>:: A hash for page numbering and text box options.
|
510
|
-
# <tt>:page_filter</tt>:: A filter to specify which pages to place page
|
511
|
-
# Refer to the method 'page_match?'
|
544
|
+
# <tt>:page_filter</tt>:: A filter to specify which pages to place page
|
545
|
+
# numbers on. Refer to the method 'page_match?'
|
512
546
|
# <tt>:start_count_at</tt>:: The starting count to increment pages from.
|
513
|
-
# <tt>:total_pages</tt>:: If provided, will replace <total> with the
|
514
|
-
# Useful to override the total
|
515
|
-
# the start_count_at
|
547
|
+
# <tt>:total_pages</tt>:: If provided, will replace <total> with the
|
548
|
+
# value given. Useful to override the total
|
549
|
+
# number of pages when using the start_count_at
|
550
|
+
# option.
|
516
551
|
# <tt>:color</tt>:: Text fill color.
|
517
552
|
#
|
518
|
-
# Please refer to Prawn::Text::text_box for additional options
|
519
|
-
# formatting and placement.
|
520
|
-
#
|
521
|
-
# Example: Print page numbers on every page except for the first. Start counting from
|
522
|
-
# five.
|
553
|
+
# Please refer to Prawn::Text::text_box for additional options
|
554
|
+
# concerning text formatting and placement.
|
523
555
|
#
|
524
|
-
#
|
525
|
-
#
|
526
|
-
#
|
527
|
-
#
|
528
|
-
#
|
529
|
-
#
|
530
|
-
#
|
531
|
-
#
|
556
|
+
# Example:
|
557
|
+
# Print page numbers on every page except for the first. Start counting
|
558
|
+
# from five.
|
559
|
+
#
|
560
|
+
# Prawn::Document.generate("page_with_numbering.pdf") do
|
561
|
+
# number_pages "<page> in a total of <total>", {
|
562
|
+
# start_count_at: 5,
|
563
|
+
# page_filter: lambda { |pg| pg != 1 },
|
564
|
+
# at: [bounds.right - 50, 0],
|
565
|
+
# align: :right,
|
566
|
+
# size: 14
|
567
|
+
# }
|
568
|
+
# end
|
532
569
|
#
|
533
|
-
def number_pages(string, options={})
|
570
|
+
def number_pages(string, options = {})
|
534
571
|
opts = options.dup
|
535
572
|
start_count_at = opts.delete(:start_count_at).to_i
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
573
|
+
|
574
|
+
page_filter =
|
575
|
+
if opts.key?(:page_filter)
|
576
|
+
opts.delete(:page_filter)
|
577
|
+
else
|
578
|
+
:all
|
579
|
+
end
|
580
|
+
|
541
581
|
total_pages = opts.delete(:total_pages)
|
542
582
|
txtcolor = opts.delete(:color)
|
543
583
|
# An explicit height so that we can draw page numbers in the margins
|
544
|
-
opts[:height] = 50 unless opts.
|
584
|
+
opts[:height] = 50 unless opts.key?(:height)
|
545
585
|
|
546
586
|
start_count = false
|
547
587
|
pseudopage = 0
|
548
588
|
(1..page_count).each do |p|
|
549
589
|
unless start_count
|
550
|
-
pseudopage =
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
590
|
+
pseudopage =
|
591
|
+
case start_count_at
|
592
|
+
when 0
|
593
|
+
1
|
594
|
+
else
|
595
|
+
start_count_at.to_i
|
596
|
+
end
|
556
597
|
end
|
557
598
|
if page_match?(page_filter, p)
|
558
599
|
go_to_page(p)
|
559
|
-
# have to use fill_color here otherwise text reverts back to default
|
600
|
+
# have to use fill_color here otherwise text reverts back to default
|
601
|
+
# fill color
|
560
602
|
fill_color txtcolor unless txtcolor.nil?
|
561
603
|
total_pages = total_pages.nil? ? page_count : total_pages
|
562
|
-
str = string.gsub(
|
604
|
+
str = string.gsub('<page>', pseudopage.to_s)
|
605
|
+
.gsub('<total>', total_pages.to_s)
|
563
606
|
text_box str, opts
|
564
|
-
start_count = true
|
607
|
+
start_count = true # increment page count as soon as first match found
|
565
608
|
end
|
566
609
|
pseudopage += 1 if start_count
|
567
610
|
end
|
568
611
|
end
|
569
612
|
|
570
|
-
# Returns true if content streams will be compressed before rendering,
|
571
|
-
# false otherwise
|
572
|
-
#
|
573
|
-
def compression_enabled?
|
574
|
-
!!state.compress
|
575
|
-
end
|
576
|
-
|
577
613
|
# @group Experimental API
|
578
614
|
|
579
615
|
# Attempts to group the given block vertically within the current context.
|
@@ -586,21 +622,21 @@ module Prawn
|
|
586
622
|
# the current page or column.
|
587
623
|
#
|
588
624
|
# @private
|
589
|
-
def group(*
|
625
|
+
def group(*_arguments)
|
590
626
|
raise NotImplementedError,
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
627
|
+
'Document#group has been disabled because its implementation ' \
|
628
|
+
'lead to corrupted documents whenever a page boundary was ' \
|
629
|
+
'crossed. We will try to work on reimplementing it in a ' \
|
630
|
+
'future release'
|
595
631
|
end
|
596
632
|
|
597
633
|
# @private
|
598
634
|
def transaction
|
599
635
|
raise NotImplementedError,
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
636
|
+
'Document#transaction has been disabled because its implementation ' \
|
637
|
+
'lead to corrupted documents whenever a page boundary was ' \
|
638
|
+
'crossed. We will try to work on reimplementing it in a ' \
|
639
|
+
'future release'
|
604
640
|
end
|
605
641
|
|
606
642
|
# Provides a way to execute a block of code repeatedly based on a
|
@@ -618,9 +654,9 @@ module Prawn
|
|
618
654
|
when :all
|
619
655
|
true
|
620
656
|
when :odd
|
621
|
-
page_number
|
657
|
+
page_number.odd?
|
622
658
|
when :even
|
623
|
-
page_number
|
659
|
+
page_number.even?
|
624
660
|
when Range, Array
|
625
661
|
page_filter.include?(page_number)
|
626
662
|
when Proc
|
@@ -631,20 +667,20 @@ module Prawn
|
|
631
667
|
# @private
|
632
668
|
|
633
669
|
def mask(*fields)
|
634
|
-
|
635
|
-
|
636
|
-
|
670
|
+
# Stores the current state of the named attributes, executes the block,
|
671
|
+
# and then restores the original values after the block has executed.
|
672
|
+
# -- I will remove the nodoc if/when this feature is a little less hacky
|
637
673
|
stored = {}
|
638
|
-
fields.each { |f| stored[f] =
|
674
|
+
fields.each { |f| stored[f] = public_send(f) }
|
639
675
|
yield
|
640
|
-
fields.each { |f|
|
676
|
+
fields.each { |f| public_send("#{f}=", stored[f]) }
|
641
677
|
end
|
642
678
|
|
643
679
|
# @group Extension API
|
644
680
|
|
645
681
|
def initialize_first_page(options)
|
646
682
|
if options[:skip_page_creation]
|
647
|
-
start_new_page(options.merge(:
|
683
|
+
start_new_page(options.merge(orphan: true))
|
648
684
|
else
|
649
685
|
start_new_page(options)
|
650
686
|
end
|
@@ -653,9 +689,7 @@ module Prawn
|
|
653
689
|
## Internals. Don't depend on them!
|
654
690
|
|
655
691
|
# @private
|
656
|
-
|
657
|
-
@internal_state
|
658
|
-
end
|
692
|
+
attr_accessor :state
|
659
693
|
|
660
694
|
# @private
|
661
695
|
def page
|
@@ -664,12 +698,11 @@ module Prawn
|
|
664
698
|
|
665
699
|
private
|
666
700
|
|
667
|
-
|
668
|
-
#
|
669
|
-
# previous settings.
|
701
|
+
# setting override_settings to true ensures that a new graphic state does
|
702
|
+
# not end up using previous settings.
|
670
703
|
def use_graphic_settings(override_settings = false)
|
671
|
-
set_fill_color if current_fill_color !=
|
672
|
-
set_stroke_color if current_stroke_color !=
|
704
|
+
set_fill_color if current_fill_color != '000000' || override_settings
|
705
|
+
set_stroke_color if current_stroke_color != '000000' || override_settings
|
673
706
|
write_line_width if line_width != 1 || override_settings
|
674
707
|
write_stroke_cap_style if cap_style != :butt || override_settings
|
675
708
|
write_stroke_join_style if join_style != :miter || override_settings
|
@@ -678,14 +711,16 @@ module Prawn
|
|
678
711
|
|
679
712
|
def generate_margin_box
|
680
713
|
old_margin_box = @margin_box
|
681
|
-
page
|
714
|
+
page = state.page
|
682
715
|
|
683
716
|
@margin_box = BoundingBox.new(
|
684
717
|
self,
|
685
|
-
nil,
|
686
|
-
[
|
687
|
-
:
|
688
|
-
|
718
|
+
nil, # margin box has no parent
|
719
|
+
[page.margins[:left], page.dimensions[-1] - page.margins[:top]],
|
720
|
+
width: page.dimensions[-2] -
|
721
|
+
(page.margins[:left] + page.margins[:right]),
|
722
|
+
height: page.dimensions[-1] -
|
723
|
+
(page.margins[:top] + page.margins[:bottom])
|
689
724
|
)
|
690
725
|
|
691
726
|
# This check maintains indentation settings across page breaks
|
@@ -696,30 +731,30 @@ module Prawn
|
|
696
731
|
|
697
732
|
# we must update bounding box if not flowing from the previous page
|
698
733
|
#
|
699
|
-
@bounding_box = @margin_box unless @bounding_box
|
734
|
+
@bounding_box = @margin_box unless @bounding_box&.parent
|
700
735
|
end
|
701
736
|
|
702
737
|
def apply_margin_options(options)
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
[
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
738
|
+
sides = %i[top right bottom left]
|
739
|
+
margin = Array(options[:margin])
|
740
|
+
|
741
|
+
# Treat :margin as CSS shorthand with 1-4 values.
|
742
|
+
positions = {
|
743
|
+
4 => [0, 1, 2, 3],
|
744
|
+
3 => [0, 1, 2, 1],
|
745
|
+
2 => [0, 1, 0, 1],
|
746
|
+
1 => [0, 0, 0, 0],
|
747
|
+
0 => []
|
748
|
+
}[margin.length]
|
749
|
+
|
750
|
+
sides.zip(positions).each do |side, pos|
|
751
|
+
new_margin = options[:"#{side}_margin"] || (margin[pos] if pos)
|
752
|
+
state.page.margins[side] = new_margin if new_margin
|
718
753
|
end
|
719
754
|
end
|
720
755
|
|
721
756
|
def font_metric_cache #:nodoc:
|
722
|
-
@font_metric_cache ||= FontMetricCache.new(
|
757
|
+
@font_metric_cache ||= FontMetricCache.new(self)
|
723
758
|
end
|
724
759
|
end
|
725
760
|
end
|