prawn 0.15.0 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|