prawn 0.15.0 → 1.0.0.rc1
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.
- data/COPYING +2 -2
- data/LICENSE +1 -1
- data/README.md +96 -0
- data/Rakefile +27 -30
- data/data/fonts/Action Man.dfont +0 -0
- data/data/fonts/Activa.ttf +0 -0
- data/data/fonts/Chalkboard.ttf +0 -0
- data/data/fonts/DejaVuSans.ttf +0 -0
- data/data/fonts/Dustismo_Roman.ttf +0 -0
- data/data/fonts/comicsans.ttf +0 -0
- data/data/fonts/gkai00mp.ttf +0 -0
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.dat +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.dat +0 -0
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.dat +0 -0
- data/data/images/rails.dat +0 -0
- data/data/images/rails.png +0 -0
- data/data/pdfs/nested_pages.pdf +13 -13
- data/lib/prawn.rb +21 -85
- data/lib/prawn/compatibility.rb +51 -0
- data/lib/prawn/core.rb +85 -0
- data/lib/prawn/core/annotations.rb +61 -0
- data/lib/prawn/core/byte_string.rb +9 -0
- data/lib/prawn/core/destinations.rb +90 -0
- data/lib/prawn/core/document_state.rb +78 -0
- data/lib/prawn/core/literal_string.rb +16 -0
- data/lib/prawn/core/name_tree.rb +177 -0
- data/lib/prawn/core/object_store.rb +264 -0
- data/lib/prawn/core/page.rb +215 -0
- data/lib/prawn/core/pdf_object.rb +108 -0
- data/lib/prawn/core/reference.rb +115 -0
- data/lib/prawn/core/text.rb +268 -0
- data/lib/prawn/core/text/formatted/arranger.rb +294 -0
- data/lib/prawn/core/text/formatted/line_wrap.rb +273 -0
- data/lib/prawn/core/text/formatted/wrap.rb +153 -0
- data/lib/prawn/document.rb +122 -155
- data/lib/prawn/document/bounding_box.rb +7 -36
- data/lib/prawn/document/column_box.rb +10 -38
- data/lib/prawn/document/graphics_state.rb +74 -11
- data/lib/prawn/document/internals.rb +23 -24
- data/lib/prawn/document/page_geometry.rb +136 -0
- data/lib/prawn/document/snapshot.rb +6 -7
- data/lib/prawn/document/span.rb +10 -12
- data/lib/prawn/encoding.rb +10 -9
- data/lib/prawn/errors.rb +30 -15
- data/lib/prawn/font.rb +104 -136
- data/lib/prawn/font/afm.rb +44 -46
- data/lib/prawn/font/dfont.rb +3 -4
- data/lib/prawn/font/ttf.rb +50 -31
- data/lib/prawn/graphics.rb +57 -302
- data/lib/prawn/graphics/cap_style.rb +3 -4
- data/lib/prawn/graphics/color.rb +5 -13
- data/lib/prawn/graphics/dash.rb +31 -53
- data/lib/prawn/graphics/gradient.rb +84 -0
- data/lib/prawn/graphics/join_style.rb +7 -9
- data/lib/prawn/graphics/transformation.rb +9 -10
- data/lib/prawn/graphics/transparency.rb +1 -3
- data/lib/prawn/images.rb +59 -69
- data/lib/prawn/images/image.rb +22 -6
- data/lib/prawn/images/jpg.rb +14 -20
- data/lib/prawn/images/png.rb +118 -61
- data/lib/prawn/layout.rb +15 -10
- data/lib/prawn/layout/grid.rb +54 -66
- data/lib/prawn/measurement_extensions.rb +6 -10
- data/lib/prawn/measurements.rb +21 -27
- data/lib/prawn/outline.rb +308 -6
- data/lib/prawn/repeater.rb +8 -10
- data/lib/prawn/security.rb +33 -55
- data/lib/prawn/security/arcfour.rb +0 -1
- data/lib/prawn/stamp.rb +3 -5
- data/lib/prawn/table.rb +60 -188
- data/lib/prawn/table/cell.rb +44 -272
- data/lib/prawn/table/cell/image.rb +3 -2
- data/lib/prawn/table/cell/in_table.rb +2 -4
- data/lib/prawn/table/cell/subtable.rb +2 -2
- data/lib/prawn/table/cell/text.rb +18 -41
- data/lib/prawn/table/cells.rb +48 -142
- data/lib/prawn/text.rb +25 -32
- data/lib/prawn/text/box.rb +6 -12
- data/lib/prawn/text/formatted.rb +4 -5
- data/lib/prawn/text/formatted/box.rb +59 -96
- data/lib/prawn/text/formatted/fragment.rb +23 -34
- data/lib/prawn/text/formatted/parser.rb +5 -15
- data/prawn.gemspec +13 -24
- data/spec/annotations_spec.rb +32 -16
- data/spec/bounding_box_spec.rb +17 -119
- data/spec/cell_spec.rb +42 -112
- data/spec/destinations_spec.rb +5 -5
- data/spec/document_spec.rb +111 -155
- data/spec/extensions/mocha.rb +0 -1
- data/spec/font_spec.rb +99 -149
- data/spec/formatted_text_arranger_spec.rb +43 -43
- data/spec/formatted_text_box_spec.rb +44 -43
- data/spec/formatted_text_fragment_spec.rb +8 -8
- data/spec/graphics_spec.rb +68 -151
- data/spec/grid_spec.rb +15 -26
- data/spec/images_spec.rb +30 -51
- data/spec/inline_formatted_text_parser_spec.rb +20 -69
- data/spec/jpg_spec.rb +4 -4
- data/spec/line_wrap_spec.rb +28 -28
- data/spec/measurement_units_spec.rb +6 -6
- data/spec/name_tree_spec.rb +112 -0
- data/spec/object_store_spec.rb +106 -17
- data/spec/outline_spec.rb +63 -103
- data/spec/pdf_object_spec.rb +170 -0
- data/spec/png_spec.rb +25 -25
- data/spec/reference_spec.rb +65 -8
- data/spec/repeater_spec.rb +10 -10
- data/spec/security_spec.rb +12 -44
- data/spec/snapshot_spec.rb +7 -7
- data/spec/span_spec.rb +15 -10
- data/spec/spec_helper.rb +8 -32
- data/spec/stamp_spec.rb +30 -29
- data/spec/stroke_styles_spec.rb +18 -36
- data/spec/table_spec.rb +111 -706
- data/spec/template_spec.rb +297 -0
- data/spec/text_at_spec.rb +33 -19
- data/spec/text_box_spec.rb +64 -100
- data/spec/text_rendering_mode_spec.rb +5 -5
- data/spec/text_spacing_spec.rb +4 -4
- data/spec/text_spec.rb +64 -84
- data/spec/transparency_spec.rb +5 -5
- metadata +290 -463
- checksums.yaml +0 -7
- data/.yardopts +0 -10
- data/Gemfile +0 -11
- data/data/images/16bit.color +0 -0
- data/data/images/dice.color +0 -0
- data/data/images/indexed_color.dat +0 -0
- data/data/images/indexed_color.png +0 -0
- data/data/images/page_white_text.color +0 -0
- data/lib/prawn/font_metric_cache.rb +0 -47
- data/lib/prawn/graphics/patterns.rb +0 -138
- data/lib/prawn/image_handler.rb +0 -36
- data/lib/prawn/soft_mask.rb +0 -96
- data/lib/prawn/table/cell/span_dummy.rb +0 -93
- data/lib/prawn/table/column_width_calculator.rb +0 -61
- data/lib/prawn/text/formatted/arranger.rb +0 -290
- data/lib/prawn/text/formatted/line_wrap.rb +0 -266
- data/lib/prawn/text/formatted/wrap.rb +0 -150
- data/lib/prawn/utilities.rb +0 -46
- data/manual/basic_concepts/adding_pages.rb +0 -27
- data/manual/basic_concepts/basic_concepts.rb +0 -34
- data/manual/basic_concepts/creation.rb +0 -39
- data/manual/basic_concepts/cursor.rb +0 -33
- data/manual/basic_concepts/measurement.rb +0 -25
- data/manual/basic_concepts/origin.rb +0 -38
- data/manual/basic_concepts/other_cursor_helpers.rb +0 -40
- data/manual/bounding_box/bounding_box.rb +0 -39
- data/manual/bounding_box/bounds.rb +0 -49
- data/manual/bounding_box/canvas.rb +0 -24
- data/manual/bounding_box/creation.rb +0 -23
- data/manual/bounding_box/indentation.rb +0 -46
- data/manual/bounding_box/nesting.rb +0 -45
- data/manual/bounding_box/russian_boxes.rb +0 -40
- data/manual/bounding_box/stretchy.rb +0 -31
- data/manual/document_and_page_options/background.rb +0 -27
- data/manual/document_and_page_options/document_and_page_options.rb +0 -32
- data/manual/document_and_page_options/metadata.rb +0 -23
- data/manual/document_and_page_options/page_margins.rb +0 -38
- data/manual/document_and_page_options/page_size.rb +0 -34
- data/manual/document_and_page_options/print_scaling.rb +0 -20
- data/manual/example_file.rb +0 -111
- data/manual/example_helper.rb +0 -411
- data/manual/example_package.rb +0 -53
- data/manual/example_section.rb +0 -46
- data/manual/graphics/circle_and_ellipse.rb +0 -22
- data/manual/graphics/color.rb +0 -24
- data/manual/graphics/common_lines.rb +0 -30
- data/manual/graphics/fill_and_stroke.rb +0 -42
- data/manual/graphics/fill_rules.rb +0 -37
- data/manual/graphics/gradients.rb +0 -37
- data/manual/graphics/graphics.rb +0 -58
- data/manual/graphics/helper.rb +0 -24
- data/manual/graphics/line_width.rb +0 -35
- data/manual/graphics/lines_and_curves.rb +0 -41
- data/manual/graphics/polygon.rb +0 -29
- data/manual/graphics/rectangle.rb +0 -21
- data/manual/graphics/rotate.rb +0 -28
- data/manual/graphics/scale.rb +0 -41
- data/manual/graphics/soft_masks.rb +0 -46
- data/manual/graphics/stroke_cap.rb +0 -31
- data/manual/graphics/stroke_dash.rb +0 -48
- data/manual/graphics/stroke_join.rb +0 -30
- data/manual/graphics/translate.rb +0 -29
- data/manual/graphics/transparency.rb +0 -35
- data/manual/images/absolute_position.rb +0 -23
- data/manual/images/fit.rb +0 -21
- data/manual/images/horizontal.rb +0 -25
- data/manual/images/images.rb +0 -40
- data/manual/images/plain_image.rb +0 -18
- data/manual/images/scale.rb +0 -22
- data/manual/images/vertical.rb +0 -28
- data/manual/images/width_and_height.rb +0 -25
- data/manual/layout/boxes.rb +0 -27
- data/manual/layout/content.rb +0 -25
- data/manual/layout/layout.rb +0 -28
- data/manual/layout/simple_grid.rb +0 -23
- data/manual/manual/cover.rb +0 -36
- data/manual/manual/foreword.rb +0 -85
- data/manual/manual/how_to_read_this_manual.rb +0 -41
- data/manual/manual/manual.rb +0 -34
- data/manual/outline/add_subsection_to.rb +0 -61
- data/manual/outline/insert_section_after.rb +0 -47
- data/manual/outline/outline.rb +0 -32
- data/manual/outline/sections_and_pages.rb +0 -67
- data/manual/repeatable_content/page_numbering.rb +0 -54
- data/manual/repeatable_content/repeatable_content.rb +0 -31
- data/manual/repeatable_content/repeater.rb +0 -55
- data/manual/repeatable_content/stamp.rb +0 -41
- data/manual/security/encryption.rb +0 -31
- data/manual/security/permissions.rb +0 -38
- data/manual/security/security.rb +0 -28
- data/manual/syntax_highlight.rb +0 -52
- 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/manual/text/alignment.rb +0 -44
- data/manual/text/color.rb +0 -24
- data/manual/text/column_box.rb +0 -32
- data/manual/text/fallback_fonts.rb +0 -37
- data/manual/text/font.rb +0 -41
- data/manual/text/font_size.rb +0 -45
- data/manual/text/font_style.rb +0 -23
- data/manual/text/formatted_callbacks.rb +0 -60
- data/manual/text/formatted_text.rb +0 -54
- data/manual/text/free_flowing_text.rb +0 -51
- data/manual/text/group.rb +0 -31
- data/manual/text/inline.rb +0 -43
- data/manual/text/kerning_and_character_spacing.rb +0 -39
- data/manual/text/leading.rb +0 -25
- data/manual/text/line_wrapping.rb +0 -41
- data/manual/text/paragraph_indentation.rb +0 -26
- data/manual/text/positioned_text.rb +0 -38
- data/manual/text/registering_families.rb +0 -48
- data/manual/text/rendering_and_color.rb +0 -37
- data/manual/text/right_to_left_text.rb +0 -43
- data/manual/text/rotation.rb +0 -43
- data/manual/text/single_usage.rb +0 -37
- data/manual/text/text.rb +0 -75
- data/manual/text/text_box_excess.rb +0 -32
- data/manual/text/text_box_extensions.rb +0 -45
- data/manual/text/text_box_overflow.rb +0 -44
- data/manual/text/utf8.rb +0 -28
- data/manual/text/win_ansi_charset.rb +0 -59
- data/spec/acceptance/png.rb +0 -23
- data/spec/column_box_spec.rb +0 -65
- data/spec/extensions/encoding_helpers.rb +0 -9
- data/spec/font_metric_cache_spec.rb +0 -52
- data/spec/image_handler_spec.rb +0 -54
- data/spec/soft_mask_spec.rb +0 -117
- data/spec/table/span_dummy_spec.rb +0 -17
@@ -0,0 +1,153 @@
|
|
1
|
+
require "prawn/core/text/formatted/line_wrap"
|
2
|
+
require "prawn/core/text/formatted/arranger"
|
3
|
+
|
4
|
+
module Prawn
|
5
|
+
module Core
|
6
|
+
module Text
|
7
|
+
module Formatted #:nodoc:
|
8
|
+
module Wrap #:nodoc:
|
9
|
+
|
10
|
+
def initialize(array, options)
|
11
|
+
@line_wrap = Prawn::Core::Text::Formatted::LineWrap.new
|
12
|
+
@arranger = Prawn::Core::Text::Formatted::Arranger.new(@document,
|
13
|
+
:kerning => options[:kerning])
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
# See the developer documentation for Prawn::Core::Text#wrap
|
18
|
+
#
|
19
|
+
# Formatted#wrap should set the following variables:
|
20
|
+
# <tt>@line_height</tt>::
|
21
|
+
# the height of the tallest fragment in the last printed line
|
22
|
+
# <tt>@descender</tt>::
|
23
|
+
# the descender height of the tallest fragment in the last
|
24
|
+
# printed line
|
25
|
+
# <tt>@ascender</tt>::
|
26
|
+
# the ascender heigth of the tallest fragment in the last
|
27
|
+
# printed line
|
28
|
+
# <tt>@baseline_y</tt>::
|
29
|
+
# the baseline of the current line
|
30
|
+
# <tt>@nothing_printed</tt>::
|
31
|
+
# set to true until something is printed, then false
|
32
|
+
# <tt>@everything_printed</tt>::
|
33
|
+
# set to false until everything printed, then true
|
34
|
+
#
|
35
|
+
# Returns any formatted text that was not printed
|
36
|
+
#
|
37
|
+
def wrap(array) #:nodoc:
|
38
|
+
initialize_wrap(array)
|
39
|
+
|
40
|
+
stop = false
|
41
|
+
while !stop
|
42
|
+
# wrap before testing if enough height for this line because the
|
43
|
+
# height of the highest fragment on this line will be used to
|
44
|
+
# determine the line height
|
45
|
+
@line_wrap.wrap_line(:document => @document,
|
46
|
+
:kerning => @kerning,
|
47
|
+
:width => available_width,
|
48
|
+
:arranger => @arranger)
|
49
|
+
|
50
|
+
if enough_height_for_this_line?
|
51
|
+
move_baseline_down
|
52
|
+
print_line
|
53
|
+
else
|
54
|
+
stop = true
|
55
|
+
end
|
56
|
+
|
57
|
+
stop ||= @single_line || @arranger.finished?
|
58
|
+
end
|
59
|
+
@text = @printed_lines.join("\n")
|
60
|
+
@everything_printed = @arranger.finished?
|
61
|
+
@arranger.unconsumed
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def print_line
|
67
|
+
@nothing_printed = false
|
68
|
+
printed_fragments = []
|
69
|
+
fragments_this_line = []
|
70
|
+
|
71
|
+
word_spacing = word_spacing_for_this_line
|
72
|
+
while fragment = @arranger.retrieve_fragment
|
73
|
+
fragment.word_spacing = word_spacing
|
74
|
+
if fragment.text == "\n"
|
75
|
+
printed_fragments << "\n" if @printed_lines.last == ""
|
76
|
+
break
|
77
|
+
end
|
78
|
+
printed_fragments << fragment.text
|
79
|
+
fragments_this_line << fragment
|
80
|
+
end
|
81
|
+
|
82
|
+
accumulated_width = 0
|
83
|
+
fragments_this_line.reverse! if @direction == :rtl
|
84
|
+
fragments_this_line.each do |fragment|
|
85
|
+
fragment.default_direction = @direction
|
86
|
+
format_and_draw_fragment(fragment, accumulated_width,
|
87
|
+
@line_wrap.width, word_spacing)
|
88
|
+
accumulated_width += fragment.width
|
89
|
+
end
|
90
|
+
|
91
|
+
if "".respond_to?(:force_encoding)
|
92
|
+
printed_fragments.map! { |s| s.force_encoding("utf-8") }
|
93
|
+
end
|
94
|
+
@printed_lines << printed_fragments.join
|
95
|
+
end
|
96
|
+
|
97
|
+
def word_spacing_for_this_line
|
98
|
+
if @align == :justify &&
|
99
|
+
@line_wrap.space_count > 0 &&
|
100
|
+
!@line_wrap.paragraph_finished?
|
101
|
+
(available_width - @line_wrap.width) / @line_wrap.space_count
|
102
|
+
else
|
103
|
+
0
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def enough_height_for_this_line?
|
108
|
+
@line_height = @arranger.max_line_height
|
109
|
+
@descender = @arranger.max_descender
|
110
|
+
@ascender = @arranger.max_ascender
|
111
|
+
if @baseline_y == 0
|
112
|
+
diff = @ascender + @descender
|
113
|
+
else
|
114
|
+
diff = @descender + @line_height + @leading
|
115
|
+
end
|
116
|
+
required_total_height = @baseline_y.abs + diff
|
117
|
+
if required_total_height > @height + 0.0001
|
118
|
+
# no room for the full height of this line
|
119
|
+
@arranger.repack_unretrieved
|
120
|
+
false
|
121
|
+
else
|
122
|
+
true
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def initialize_wrap(array)
|
127
|
+
@text = nil
|
128
|
+
@arranger.format_array = array
|
129
|
+
|
130
|
+
# these values will depend on the maximum value within a given line
|
131
|
+
@line_height = 0
|
132
|
+
@descender = 0
|
133
|
+
@ascender = 0
|
134
|
+
@baseline_y = 0
|
135
|
+
|
136
|
+
@printed_lines = []
|
137
|
+
@nothing_printed = true
|
138
|
+
@everything_printed = false
|
139
|
+
end
|
140
|
+
|
141
|
+
def format_and_draw_fragment(fragment, accumulated_width,
|
142
|
+
line_width, word_spacing)
|
143
|
+
@arranger.apply_color_and_font_settings(fragment) do
|
144
|
+
draw_fragment(fragment, accumulated_width,
|
145
|
+
line_width, word_spacing)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
data/lib/prawn/document.rb
CHANGED
@@ -7,13 +7,13 @@
|
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
|
9
9
|
require "stringio"
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
require "prawn/document/page_geometry"
|
11
|
+
require "prawn/document/bounding_box"
|
12
|
+
require "prawn/document/column_box"
|
13
|
+
require "prawn/document/internals"
|
14
|
+
require "prawn/document/span"
|
15
|
+
require "prawn/document/snapshot"
|
16
|
+
require "prawn/document/graphics_state"
|
17
17
|
|
18
18
|
module Prawn
|
19
19
|
|
@@ -52,8 +52,8 @@ module Prawn
|
|
52
52
|
#
|
53
53
|
class Document
|
54
54
|
include Prawn::Document::Internals
|
55
|
-
include
|
56
|
-
include
|
55
|
+
include Prawn::Core::Annotations
|
56
|
+
include Prawn::Core::Destinations
|
57
57
|
include Prawn::Document::Snapshot
|
58
58
|
include Prawn::Document::GraphicsState
|
59
59
|
include Prawn::Document::Security
|
@@ -61,17 +61,6 @@ module Prawn
|
|
61
61
|
include Prawn::Graphics
|
62
62
|
include Prawn::Images
|
63
63
|
include Prawn::Stamp
|
64
|
-
include Prawn::SoftMask
|
65
|
-
|
66
|
-
# @group Extension API
|
67
|
-
|
68
|
-
# NOTE: We probably need to rethink the options validation system, but this
|
69
|
-
# constant temporarily allows for extensions to modify the list.
|
70
|
-
|
71
|
-
VALID_OPTIONS = [:page_size, :page_layout, :margin, :left_margin,
|
72
|
-
:right_margin, :top_margin, :bottom_margin, :skip_page_creation,
|
73
|
-
:compress, :skip_encoding, :background, :info,
|
74
|
-
:optimize_objects, :text_formatter, :print_scaling]
|
75
64
|
|
76
65
|
# Any module added to this array will be included into instances of
|
77
66
|
# Prawn::Document at the per-object level. These will also be inherited by
|
@@ -93,28 +82,14 @@ module Prawn
|
|
93
82
|
# party!
|
94
83
|
# end
|
95
84
|
#
|
96
|
-
#
|
97
85
|
def self.extensions
|
98
86
|
@extensions ||= []
|
99
87
|
end
|
100
88
|
|
101
|
-
|
102
|
-
def self.inherited(base)
|
89
|
+
def self.inherited(base) #:nodoc:
|
103
90
|
extensions.each { |e| base.extensions << e }
|
104
91
|
end
|
105
92
|
|
106
|
-
# @group Stable Attributes
|
107
|
-
|
108
|
-
attr_accessor :margin_box
|
109
|
-
attr_reader :margins, :y
|
110
|
-
attr_accessor :page_number
|
111
|
-
|
112
|
-
# @group Extension Attributes
|
113
|
-
|
114
|
-
attr_accessor :text_formatter
|
115
|
-
|
116
|
-
# @group Stable API
|
117
|
-
|
118
93
|
# Creates and renders a PDF document.
|
119
94
|
#
|
120
95
|
# When using the implicit block form, Prawn will evaluate the block
|
@@ -161,9 +136,8 @@ module Prawn
|
|
161
136
|
# <tt>:compress</tt>:: Compresses content streams before rendering them [false]
|
162
137
|
# <tt>:optimize_objects</tt>:: Reduce number of PDF objects in output, at expense of render time [false]
|
163
138
|
# <tt>:background</tt>:: An image path to be used as background on all pages [nil]
|
164
|
-
# <tt>:background_scale</tt>:: Backgound image scale [1] [nil]
|
165
139
|
# <tt>:info</tt>:: Generic hash allowing for custom metadata properties [nil]
|
166
|
-
# <tt>:
|
140
|
+
# <tt>:template</tt>:: The path to an existing PDF file to use as a template [nil]
|
167
141
|
#
|
168
142
|
# Setting e.g. the :margin to 100 points and the :left_margin to 50 will result in margins
|
169
143
|
# of 100 points on every side except for the left, where it will be 50.
|
@@ -192,25 +166,25 @@ module Prawn
|
|
192
166
|
# pdf = Prawn::Document.new(:page_size => [200, 300])
|
193
167
|
#
|
194
168
|
# # New document, with background
|
195
|
-
# pdf = Prawn::Document.new(:background => "#{Prawn::
|
169
|
+
# pdf = Prawn::Document.new(:background => "#{Prawn::BASEDIR}/data/images/pigs.jpg")
|
196
170
|
#
|
197
171
|
def initialize(options={},&block)
|
198
172
|
options = options.dup
|
199
173
|
|
200
|
-
Prawn.verify_options
|
174
|
+
Prawn.verify_options [:page_size, :page_layout, :margin, :left_margin,
|
175
|
+
:right_margin, :top_margin, :bottom_margin, :skip_page_creation,
|
176
|
+
:compress, :skip_encoding, :background, :info,
|
177
|
+
:optimize_objects, :template], options
|
201
178
|
|
202
179
|
# need to fix, as the refactoring breaks this
|
203
180
|
# raise NotImplementedError if options[:skip_page_creation]
|
204
181
|
|
205
182
|
self.class.extensions.reverse_each { |e| extend e }
|
206
|
-
@internal_state =
|
183
|
+
@internal_state = Prawn::Core::DocumentState.new(options)
|
207
184
|
@internal_state.populate_pages_from_store(self)
|
208
185
|
min_version(state.store.min_version) if state.store.min_version
|
209
186
|
|
210
|
-
min_version(1.6) if options[:print_scaling] == :none
|
211
|
-
|
212
187
|
@background = options[:background]
|
213
|
-
@background_scale = options[:background_scale] || 1
|
214
188
|
@font_size = 12
|
215
189
|
|
216
190
|
@bounding_box = nil
|
@@ -218,12 +192,19 @@ module Prawn
|
|
218
192
|
|
219
193
|
@page_number = 0
|
220
194
|
|
221
|
-
@text_formatter = options.delete(:text_formatter) || Text::Formatted::Parser
|
222
|
-
|
223
195
|
options[:size] = options.delete(:page_size)
|
224
196
|
options[:layout] = options.delete(:page_layout)
|
225
197
|
|
226
|
-
|
198
|
+
if options[:template]
|
199
|
+
fresh_content_streams(options)
|
200
|
+
go_to_page(1)
|
201
|
+
else
|
202
|
+
if options[:skip_page_creation] || options[:template]
|
203
|
+
start_new_page(options.merge(:orphan => true))
|
204
|
+
else
|
205
|
+
start_new_page(options)
|
206
|
+
end
|
207
|
+
end
|
227
208
|
|
228
209
|
@bounding_box = @margin_box
|
229
210
|
|
@@ -232,7 +213,18 @@ module Prawn
|
|
232
213
|
end
|
233
214
|
end
|
234
215
|
|
235
|
-
|
216
|
+
attr_accessor :margin_box
|
217
|
+
attr_reader :margins, :y
|
218
|
+
attr_writer :font_size
|
219
|
+
attr_accessor :page_number
|
220
|
+
|
221
|
+
def state
|
222
|
+
@internal_state
|
223
|
+
end
|
224
|
+
|
225
|
+
def page
|
226
|
+
state.page
|
227
|
+
end
|
236
228
|
|
237
229
|
# Creates and advances to a new page in the document.
|
238
230
|
#
|
@@ -244,6 +236,11 @@ module Prawn
|
|
244
236
|
# pdf.start_new_page(:left_margin => 50, :right_margin => 50)
|
245
237
|
# pdf.start_new_page(:margin => 100)
|
246
238
|
#
|
239
|
+
# A template for a page can be specified by pointing to the path of and existing pdf.
|
240
|
+
# One can also specify which page of the template which defaults otherwise to 1.
|
241
|
+
#
|
242
|
+
# pdf.start_new_page(:template => multipage_template.pdf, :template_page => 2)
|
243
|
+
#
|
247
244
|
def start_new_page(options = {})
|
248
245
|
if last_page = state.page
|
249
246
|
last_page_size = last_page.size
|
@@ -255,13 +252,14 @@ module Prawn
|
|
255
252
|
:layout => options[:layout] || last_page_layout,
|
256
253
|
:margins => last_page_margins}
|
257
254
|
if last_page
|
258
|
-
new_graphic_state = last_page.graphic_state.dup
|
255
|
+
new_graphic_state = last_page.graphic_state.dup
|
259
256
|
#erase the color space so that it gets reset on new page for fussy pdf-readers
|
260
|
-
new_graphic_state.color_space = {}
|
257
|
+
new_graphic_state.color_space = {}
|
261
258
|
page_options.merge!(:graphic_state => new_graphic_state)
|
262
259
|
end
|
260
|
+
merge_template_options(page_options, options) if options[:template]
|
263
261
|
|
264
|
-
state.page =
|
262
|
+
state.page = Prawn::Core::Page.new(self, page_options)
|
265
263
|
|
266
264
|
apply_margin_options(options)
|
267
265
|
generate_margin_box
|
@@ -272,13 +270,14 @@ module Prawn
|
|
272
270
|
@bounding_box = @margin_box
|
273
271
|
end
|
274
272
|
|
275
|
-
|
273
|
+
state.page.new_content_stream if options[:template]
|
274
|
+
use_graphic_settings(options[:template])
|
276
275
|
|
277
276
|
unless options[:orphan]
|
278
277
|
state.insert_page(state.page, @page_number)
|
279
278
|
@page_number += 1
|
280
279
|
|
281
|
-
canvas { image(@background, :
|
280
|
+
canvas { image(@background, :at => bounds.top_left) } if @background
|
282
281
|
@y = @bounding_box.absolute_top
|
283
282
|
|
284
283
|
float do
|
@@ -349,26 +348,19 @@ module Prawn
|
|
349
348
|
self.y = original_y
|
350
349
|
end
|
351
350
|
|
352
|
-
# Renders the PDF document to string
|
353
|
-
# Pass an open file descriptor to render to file.
|
351
|
+
# Renders the PDF document to string
|
354
352
|
#
|
355
|
-
def render
|
356
|
-
|
357
|
-
output.set_encoding(::Encoding::ASCII_8BIT)
|
358
|
-
end
|
353
|
+
def render
|
354
|
+
output = StringIO.new
|
359
355
|
finalize_all_page_contents
|
360
356
|
|
361
357
|
render_header(output)
|
362
358
|
render_body(output)
|
363
359
|
render_xref(output)
|
364
360
|
render_trailer(output)
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
return str
|
369
|
-
else
|
370
|
-
return nil
|
371
|
-
end
|
361
|
+
str = output.string
|
362
|
+
str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
|
363
|
+
str
|
372
364
|
end
|
373
365
|
|
374
366
|
# Renders the PDF document to file.
|
@@ -376,7 +368,8 @@ module Prawn
|
|
376
368
|
# pdf.render_file "foo.pdf"
|
377
369
|
#
|
378
370
|
def render_file(filename)
|
379
|
-
|
371
|
+
Kernel.const_defined?("Encoding") ? mode = "wb:ASCII-8BIT" : mode = "wb"
|
372
|
+
File.open(filename,mode) { |f| f << render }
|
380
373
|
end
|
381
374
|
|
382
375
|
# The bounds method returns the current bounding box you are currently in,
|
@@ -412,7 +405,6 @@ module Prawn
|
|
412
405
|
|
413
406
|
# Returns the innermost non-stretchy bounding box.
|
414
407
|
#
|
415
|
-
# @private
|
416
408
|
def reference_bounds
|
417
409
|
@bounding_box.reference_bounds
|
418
410
|
end
|
@@ -498,6 +490,47 @@ module Prawn
|
|
498
490
|
bounds.indent(left, right, &block)
|
499
491
|
end
|
500
492
|
|
493
|
+
|
494
|
+
def mask(*fields) # :nodoc:
|
495
|
+
# Stores the current state of the named attributes, executes the block, and
|
496
|
+
# then restores the original values after the block has executed.
|
497
|
+
# -- I will remove the nodoc if/when this feature is a little less hacky
|
498
|
+
stored = {}
|
499
|
+
fields.each { |f| stored[f] = send(f) }
|
500
|
+
yield
|
501
|
+
fields.each { |f| send("#{f}=", stored[f]) }
|
502
|
+
end
|
503
|
+
|
504
|
+
# Attempts to group the given block vertically within the current context.
|
505
|
+
# First attempts to render it in the current position on the current page.
|
506
|
+
# If that attempt overflows, it is tried anew after starting a new context
|
507
|
+
# (page or column). Returns a logically true value if the content fits in
|
508
|
+
# one page/column, false if a new page or column was needed.
|
509
|
+
#
|
510
|
+
# Raises CannotGroup if the provided content is too large to fit alone in
|
511
|
+
# the current page or column.
|
512
|
+
#
|
513
|
+
def group(second_attempt=false)
|
514
|
+
old_bounding_box = @bounding_box
|
515
|
+
@bounding_box = SimpleDelegator.new(@bounding_box)
|
516
|
+
|
517
|
+
def @bounding_box.move_past_bottom
|
518
|
+
raise RollbackTransaction
|
519
|
+
end
|
520
|
+
|
521
|
+
success = transaction { yield }
|
522
|
+
|
523
|
+
@bounding_box = old_bounding_box
|
524
|
+
|
525
|
+
unless success
|
526
|
+
raise Prawn::Errors::CannotGroup if second_attempt
|
527
|
+
old_bounding_box.move_past_bottom
|
528
|
+
group(second_attempt=true) { yield }
|
529
|
+
end
|
530
|
+
|
531
|
+
success
|
532
|
+
end
|
533
|
+
|
501
534
|
# Places a text box on specified pages for page numbering. This should be called
|
502
535
|
# towards the end of document creation, after all your content is already in
|
503
536
|
# place. In your template string, <page> refers to the current page, and
|
@@ -506,15 +539,15 @@ module Prawn
|
|
506
539
|
# through existing pages after they are created.
|
507
540
|
#
|
508
541
|
# Parameters are:
|
509
|
-
#
|
510
|
-
# <tt>string</tt>:: Template string for page number wording.
|
542
|
+
#
|
543
|
+
# <tt>string</tt>:: Template string for page number wording.
|
511
544
|
# Should include '<page>' and, optionally, '<total>'.
|
512
545
|
# <tt>options</tt>:: A hash for page numbering and text box options.
|
513
|
-
# <tt>:page_filter</tt>:: A filter to specify which pages to place page numbers on.
|
546
|
+
# <tt>:page_filter</tt>:: A filter to specify which pages to place page numbers on.
|
514
547
|
# Refer to the method 'page_match?'
|
515
548
|
# <tt>:start_count_at</tt>:: The starting count to increment pages from.
|
516
549
|
# <tt>:total_pages</tt>:: If provided, will replace <total> with the value given.
|
517
|
-
# Useful to override the total number of pages when using
|
550
|
+
# Useful to override the total number of pages when using
|
518
551
|
# the start_count_at option.
|
519
552
|
# <tt>:color</tt>:: Text fill color.
|
520
553
|
#
|
@@ -525,7 +558,7 @@ module Prawn
|
|
525
558
|
# five.
|
526
559
|
#
|
527
560
|
# Prawn::Document.generate("page_with_numbering.pdf") do
|
528
|
-
# number_pages "<page> in a total of <total>",
|
561
|
+
# number_pages "<page> in a total of <total>",
|
529
562
|
# {:start_count_at => 5,
|
530
563
|
# :page_filter => lambda{ |pg| pg != 1 },
|
531
564
|
# :at => [bounds.right - 50, 0],
|
@@ -544,8 +577,8 @@ module Prawn
|
|
544
577
|
total_pages = opts.delete(:total_pages)
|
545
578
|
txtcolor = opts.delete(:color)
|
546
579
|
# An explicit height so that we can draw page numbers in the margins
|
547
|
-
opts[:height] = 50
|
548
|
-
|
580
|
+
opts[:height] = 50
|
581
|
+
|
549
582
|
start_count = false
|
550
583
|
pseudopage = 0
|
551
584
|
(1..page_count).each do |p|
|
@@ -556,7 +589,7 @@ module Prawn
|
|
556
589
|
else
|
557
590
|
start_count_at.to_i
|
558
591
|
end
|
559
|
-
end
|
592
|
+
end
|
560
593
|
if page_match?(page_filter, p)
|
561
594
|
go_to_page(p)
|
562
595
|
# have to use fill_color here otherwise text reverts back to default fill color
|
@@ -565,53 +598,13 @@ module Prawn
|
|
565
598
|
str = string.gsub("<page>","#{pseudopage}").gsub("<total>","#{total_pages}")
|
566
599
|
text_box str, opts
|
567
600
|
start_count = true # increment page count as soon as first match found
|
568
|
-
end
|
601
|
+
end
|
569
602
|
pseudopage += 1 if start_count
|
570
603
|
end
|
571
604
|
end
|
572
605
|
|
573
|
-
# Returns true if content streams will be compressed before rendering,
|
574
|
-
# false otherwise
|
575
|
-
#
|
576
|
-
def compression_enabled?
|
577
|
-
!!state.compress
|
578
|
-
end
|
579
|
-
|
580
|
-
# @group Experimental API
|
581
|
-
|
582
|
-
# Attempts to group the given block vertically within the current context.
|
583
|
-
# First attempts to render it in the current position on the current page.
|
584
|
-
# If that attempt overflows, it is tried anew after starting a new context
|
585
|
-
# (page or column). Returns a logically true value if the content fits in
|
586
|
-
# one page/column, false if a new page or column was needed.
|
587
|
-
#
|
588
|
-
# Raises CannotGroup if the provided content is too large to fit alone in
|
589
|
-
# the current page or column.
|
590
|
-
#
|
591
|
-
def group(second_attempt=false)
|
592
|
-
old_bounding_box = @bounding_box
|
593
|
-
@bounding_box = SimpleDelegator.new(@bounding_box)
|
594
|
-
|
595
|
-
# @private
|
596
|
-
def @bounding_box.move_past_bottom
|
597
|
-
raise RollbackTransaction
|
598
|
-
end
|
599
|
-
|
600
|
-
success = transaction { yield }
|
601
|
-
|
602
|
-
@bounding_box = old_bounding_box
|
603
|
-
|
604
|
-
unless success
|
605
|
-
raise Prawn::Errors::CannotGroup if second_attempt
|
606
|
-
old_bounding_box.move_past_bottom
|
607
|
-
group(second_attempt=true) { yield }
|
608
|
-
end
|
609
|
-
|
610
|
-
success
|
611
|
-
end
|
612
|
-
|
613
606
|
# Provides a way to execute a block of code repeatedly based on a
|
614
|
-
# page_filter.
|
607
|
+
# page_filter.
|
615
608
|
#
|
616
609
|
# Available page filters are:
|
617
610
|
# :all repeats on every page
|
@@ -619,7 +612,7 @@ module Prawn
|
|
619
612
|
# :even repeats on even pages
|
620
613
|
# some_array repeats on every page listed in the array
|
621
614
|
# some_range repeats on every page included in the range
|
622
|
-
# some_lambda yields page number and repeats for true return values
|
615
|
+
# some_lambda yields page number and repeats for true return values
|
623
616
|
def page_match?(page_filter, page_number)
|
624
617
|
case page_filter
|
625
618
|
when :all
|
@@ -633,47 +626,25 @@ module Prawn
|
|
633
626
|
when Proc
|
634
627
|
page_filter.call(page_number)
|
635
628
|
end
|
636
|
-
end
|
637
|
-
|
638
|
-
# @private
|
639
|
-
|
640
|
-
def mask(*fields)
|
641
|
-
# Stores the current state of the named attributes, executes the block, and
|
642
|
-
# then restores the original values after the block has executed.
|
643
|
-
# -- I will remove the nodoc if/when this feature is a little less hacky
|
644
|
-
stored = {}
|
645
|
-
fields.each { |f| stored[f] = send(f) }
|
646
|
-
yield
|
647
|
-
fields.each { |f| send("#{f}=", stored[f]) }
|
648
|
-
end
|
649
|
-
|
650
|
-
# @group Extension API
|
651
|
-
|
652
|
-
def initialize_first_page(options)
|
653
|
-
if options[:skip_page_creation]
|
654
|
-
start_new_page(options.merge(:orphan => true))
|
655
|
-
else
|
656
|
-
start_new_page(options)
|
657
|
-
end
|
658
|
-
end
|
629
|
+
end
|
659
630
|
|
660
|
-
## Internals. Don't depend on them!
|
661
631
|
|
662
|
-
#
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
# @private
|
668
|
-
def page
|
669
|
-
state.page
|
632
|
+
# Returns true if content streams will be compressed before rendering,
|
633
|
+
# false otherwise
|
634
|
+
#
|
635
|
+
def compression_enabled?
|
636
|
+
!!state.compress
|
670
637
|
end
|
671
638
|
|
672
639
|
private
|
673
640
|
|
641
|
+
def merge_template_options(page_options, options)
|
642
|
+
object_id = state.store.import_page(options[:template], options[:template_page] || 1)
|
643
|
+
page_options.merge!(:object_id => object_id )
|
644
|
+
end
|
674
645
|
|
675
646
|
# setting override_settings to true ensures that a new graphic state does not end up using
|
676
|
-
# previous settings
|
647
|
+
# previous settings especially from imported template streams
|
677
648
|
def use_graphic_settings(override_settings = false)
|
678
649
|
set_fill_color if current_fill_color != "000000" || override_settings
|
679
650
|
set_stroke_color if current_stroke_color != "000000" || override_settings
|
@@ -726,9 +697,5 @@ module Prawn
|
|
726
697
|
end
|
727
698
|
end
|
728
699
|
end
|
729
|
-
|
730
|
-
def font_metric_cache #:nodoc:
|
731
|
-
@font_metric_cache ||= FontMetricCache.new( self )
|
732
|
-
end
|
733
700
|
end
|
734
701
|
end
|