prawn 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/COPYING +2 -2
- data/Gemfile +18 -0
- data/LICENSE +1 -1
- data/README.md +17 -4
- data/Rakefile +18 -22
- data/data/images/indexed_color.dat +0 -0
- data/data/images/indexed_color.png +0 -0
- data/data/pdfs/nested_pages.pdf +13 -13
- data/lib/pdf/core.rb +35 -0
- data/lib/{prawn → pdf}/core/annotations.rb +6 -7
- data/lib/{prawn → pdf}/core/byte_string.rb +1 -1
- data/lib/{prawn → pdf}/core/destinations.rb +23 -23
- data/lib/{prawn → pdf}/core/document_state.rb +8 -8
- data/lib/pdf/core/filter_list.rb +51 -0
- data/lib/pdf/core/filters.rb +36 -0
- data/lib/pdf/core/graphics_state.rb +68 -0
- data/lib/{prawn → pdf}/core/literal_string.rb +1 -1
- data/lib/{prawn → pdf}/core/name_tree.rb +14 -2
- data/lib/{prawn → pdf}/core/object_store.rb +80 -24
- data/lib/pdf/core/outline.rb +315 -0
- data/lib/{prawn → pdf}/core/page.rb +23 -26
- data/lib/{prawn/document → pdf/core}/page_geometry.rb +11 -21
- data/lib/{prawn → pdf}/core/pdf_object.rb +48 -32
- data/lib/{prawn → pdf}/core/reference.rb +35 -44
- data/lib/pdf/core/stream.rb +98 -0
- data/lib/{prawn → pdf}/core/text.rb +24 -17
- data/lib/prawn.rb +95 -17
- data/lib/prawn/compatibility.rb +66 -26
- data/lib/prawn/document.rb +48 -30
- data/lib/prawn/document/bounding_box.rb +3 -3
- data/lib/prawn/document/column_box.rb +46 -8
- data/lib/prawn/document/graphics_state.rb +10 -73
- data/lib/prawn/document/internals.rb +24 -23
- data/lib/prawn/document/snapshot.rb +6 -7
- data/lib/prawn/document/span.rb +10 -10
- data/lib/prawn/encoding.rb +7 -7
- data/lib/prawn/errors.rb +18 -29
- data/lib/prawn/font.rb +64 -28
- data/lib/prawn/font/afm.rb +32 -74
- data/lib/prawn/font/dfont.rb +2 -2
- data/lib/prawn/font/ttf.rb +28 -57
- data/lib/prawn/font_metric_cache.rb +45 -0
- data/lib/prawn/graphics.rb +307 -41
- data/lib/prawn/graphics/cap_style.rb +3 -3
- data/lib/prawn/graphics/color.rb +12 -5
- data/lib/prawn/graphics/dash.rb +52 -31
- data/lib/prawn/graphics/join_style.rb +7 -7
- data/lib/prawn/graphics/patterns.rb +137 -0
- data/lib/prawn/graphics/transformation.rb +9 -9
- data/lib/prawn/graphics/transparency.rb +1 -1
- data/lib/prawn/image_handler.rb +30 -0
- data/lib/prawn/images.rb +86 -105
- data/lib/prawn/images/image.rb +48 -0
- data/lib/prawn/images/jpg.rb +14 -10
- data/lib/prawn/images/png.rb +50 -37
- data/lib/prawn/layout.rb +2 -2
- data/lib/prawn/layout/grid.rb +51 -51
- data/lib/prawn/measurement_extensions.rb +5 -5
- data/lib/prawn/measurements.rb +25 -21
- data/lib/prawn/outline.rb +4 -308
- data/lib/prawn/repeater.rb +8 -8
- data/lib/prawn/security.rb +50 -36
- data/lib/prawn/soft_mask.rb +94 -0
- data/lib/prawn/stamp.rb +3 -3
- data/lib/prawn/table.rb +292 -118
- data/lib/prawn/table/cell.rb +272 -45
- data/lib/prawn/table/cell/image.rb +70 -0
- data/lib/prawn/table/cell/in_table.rb +2 -2
- data/lib/prawn/table/cell/span_dummy.rb +92 -0
- data/lib/prawn/table/cell/subtable.rb +2 -2
- data/lib/prawn/table/cell/text.rb +42 -24
- data/lib/prawn/table/cells.rb +137 -48
- data/lib/prawn/text.rb +35 -23
- data/lib/prawn/text/box.rb +18 -5
- data/lib/prawn/text/formatted.rb +5 -4
- data/lib/prawn/text/formatted/arranger.rb +292 -0
- data/lib/prawn/text/formatted/box.rb +52 -13
- data/lib/prawn/text/formatted/fragment.rb +37 -22
- data/lib/prawn/text/formatted/line_wrap.rb +286 -0
- data/lib/prawn/text/formatted/parser.rb +14 -6
- data/lib/prawn/text/formatted/wrap.rb +151 -0
- data/lib/prawn/utilities.rb +44 -0
- data/manual/basic_concepts/adding_pages.rb +27 -0
- data/manual/basic_concepts/basic_concepts.rb +34 -0
- data/manual/basic_concepts/creation.rb +39 -0
- data/manual/basic_concepts/cursor.rb +33 -0
- data/manual/basic_concepts/measurement.rb +25 -0
- data/manual/basic_concepts/origin.rb +38 -0
- data/manual/basic_concepts/other_cursor_helpers.rb +40 -0
- data/manual/bounding_box/bounding_box.rb +39 -0
- data/manual/bounding_box/bounds.rb +49 -0
- data/manual/bounding_box/canvas.rb +24 -0
- data/manual/bounding_box/creation.rb +23 -0
- data/manual/bounding_box/indentation.rb +46 -0
- data/manual/bounding_box/nesting.rb +45 -0
- data/manual/bounding_box/russian_boxes.rb +40 -0
- data/manual/bounding_box/stretchy.rb +31 -0
- data/manual/document_and_page_options/background.rb +27 -0
- data/manual/document_and_page_options/document_and_page_options.rb +31 -0
- data/manual/document_and_page_options/metadata.rb +23 -0
- data/manual/document_and_page_options/page_margins.rb +38 -0
- data/manual/document_and_page_options/page_size.rb +34 -0
- data/manual/example_file.rb +116 -0
- data/manual/example_helper.rb +411 -0
- data/manual/example_package.rb +53 -0
- data/manual/example_section.rb +46 -0
- data/manual/graphics/circle_and_ellipse.rb +22 -0
- data/manual/graphics/color.rb +24 -0
- data/manual/graphics/common_lines.rb +28 -0
- data/manual/graphics/fill_and_stroke.rb +42 -0
- data/manual/graphics/fill_rules.rb +37 -0
- data/manual/graphics/gradients.rb +37 -0
- data/manual/graphics/graphics.rb +58 -0
- data/manual/graphics/helper.rb +24 -0
- data/manual/graphics/line_width.rb +35 -0
- data/manual/graphics/lines_and_curves.rb +41 -0
- data/manual/graphics/polygon.rb +29 -0
- data/manual/graphics/rectangle.rb +21 -0
- data/manual/graphics/rotate.rb +28 -0
- data/manual/graphics/scale.rb +41 -0
- data/manual/graphics/soft_masks.rb +46 -0
- data/manual/graphics/stroke_cap.rb +31 -0
- data/manual/graphics/stroke_dash.rb +48 -0
- data/manual/graphics/stroke_join.rb +30 -0
- data/manual/graphics/translate.rb +29 -0
- data/manual/graphics/transparency.rb +35 -0
- data/manual/images/absolute_position.rb +23 -0
- data/manual/images/fit.rb +21 -0
- data/manual/images/horizontal.rb +25 -0
- data/manual/images/images.rb +40 -0
- data/manual/images/plain_image.rb +18 -0
- data/manual/images/scale.rb +22 -0
- data/manual/images/vertical.rb +28 -0
- data/manual/images/width_and_height.rb +25 -0
- data/manual/layout/boxes.rb +27 -0
- data/manual/layout/content.rb +25 -0
- data/manual/layout/layout.rb +28 -0
- data/manual/layout/simple_grid.rb +23 -0
- data/manual/manual/cover.rb +35 -0
- data/manual/manual/foreword.rb +85 -0
- data/manual/manual/how_to_read_this_manual.rb +41 -0
- data/manual/manual/manual.rb +35 -0
- data/manual/outline/add_subsection_to.rb +61 -0
- data/manual/outline/insert_section_after.rb +47 -0
- data/manual/outline/outline.rb +32 -0
- data/manual/outline/sections_and_pages.rb +67 -0
- data/manual/repeatable_content/page_numbering.rb +54 -0
- data/manual/repeatable_content/repeatable_content.rb +31 -0
- data/manual/repeatable_content/repeater.rb +55 -0
- data/manual/repeatable_content/stamp.rb +41 -0
- data/manual/security/encryption.rb +31 -0
- data/manual/security/permissions.rb +38 -0
- data/manual/security/security.rb +28 -0
- data/manual/syntax_highlight.rb +52 -0
- data/manual/table/basic_block.rb +53 -0
- data/manual/table/before_rendering_page.rb +26 -0
- data/manual/table/cell_border_lines.rb +24 -0
- data/manual/table/cell_borders_and_bg.rb +31 -0
- data/manual/table/cell_dimensions.rb +30 -0
- data/manual/table/cell_text.rb +38 -0
- data/manual/table/column_widths.rb +30 -0
- data/manual/table/content_and_subtables.rb +39 -0
- data/manual/table/creation.rb +27 -0
- data/manual/table/filtering.rb +36 -0
- data/manual/table/flow_and_header.rb +17 -0
- data/manual/table/image_cells.rb +33 -0
- data/manual/table/position.rb +29 -0
- data/manual/table/row_colors.rb +20 -0
- data/manual/table/span.rb +30 -0
- data/manual/table/style.rb +22 -0
- data/manual/table/table.rb +52 -0
- data/manual/table/width.rb +27 -0
- data/manual/templates/full_template.rb +25 -0
- data/manual/templates/page_template.rb +48 -0
- data/manual/templates/templates.rb +27 -0
- data/manual/text/alignment.rb +44 -0
- data/manual/text/color.rb +24 -0
- data/manual/text/column_box.rb +32 -0
- data/manual/text/fallback_fonts.rb +37 -0
- data/manual/text/font.rb +41 -0
- data/manual/text/font_size.rb +45 -0
- data/manual/text/font_style.rb +23 -0
- data/manual/text/formatted_callbacks.rb +60 -0
- data/manual/text/formatted_text.rb +54 -0
- data/manual/text/free_flowing_text.rb +51 -0
- data/manual/text/group.rb +29 -0
- data/manual/text/inline.rb +43 -0
- data/manual/text/kerning_and_character_spacing.rb +39 -0
- data/manual/text/leading.rb +25 -0
- data/manual/text/line_wrapping.rb +41 -0
- data/manual/text/paragraph_indentation.rb +26 -0
- data/manual/text/positioned_text.rb +38 -0
- data/manual/text/registering_families.rb +48 -0
- data/manual/text/rendering_and_color.rb +37 -0
- data/manual/text/right_to_left_text.rb +43 -0
- data/manual/text/rotation.rb +43 -0
- data/manual/text/single_usage.rb +37 -0
- data/manual/text/text.rb +75 -0
- data/manual/text/text_box_excess.rb +32 -0
- data/manual/text/text_box_extensions.rb +45 -0
- data/manual/text/text_box_overflow.rb +44 -0
- data/manual/text/utf8.rb +28 -0
- data/{examples/m17n → manual/text}/win_ansi_charset.rb +14 -10
- data/prawn.gemspec +18 -12
- data/spec/acceptance/png.rb +23 -0
- data/spec/annotations_spec.rb +16 -32
- data/spec/bounding_box_spec.rb +128 -15
- data/spec/cell_spec.rb +169 -38
- data/spec/column_box_spec.rb +33 -0
- data/spec/destinations_spec.rb +5 -5
- data/spec/document_spec.rb +150 -104
- data/spec/extensions/encoding_helpers.rb +10 -0
- data/spec/extensions/mocha.rb +1 -0
- data/spec/filters_spec.rb +34 -0
- data/spec/font_metric_cache_spec.rb +52 -0
- data/spec/font_spec.rb +183 -97
- data/spec/formatted_text_arranger_spec.rb +43 -43
- data/spec/formatted_text_box_spec.rb +30 -20
- data/spec/formatted_text_fragment_spec.rb +8 -8
- data/spec/graphics_spec.rb +158 -69
- data/spec/grid_spec.rb +15 -15
- data/spec/image_handler_spec.rb +42 -0
- data/spec/images_spec.rb +49 -24
- data/spec/inline_formatted_text_parser_spec.rb +73 -19
- data/spec/jpg_spec.rb +4 -4
- data/spec/line_wrap_spec.rb +26 -26
- data/spec/measurement_units_spec.rb +6 -6
- data/spec/name_tree_spec.rb +21 -21
- data/spec/object_store_spec.rb +39 -39
- data/spec/outline_spec.rb +93 -53
- data/spec/pdf_object_spec.rb +88 -86
- data/spec/png_spec.rb +31 -28
- data/spec/reference_spec.rb +32 -32
- data/spec/repeater_spec.rb +25 -11
- data/spec/security_spec.rb +44 -12
- data/spec/snapshot_spec.rb +8 -9
- data/spec/soft_mask_spec.rb +117 -0
- data/spec/span_spec.rb +10 -15
- data/spec/spec_helper.rb +25 -8
- data/spec/stamp_spec.rb +29 -30
- data/spec/stream_spec.rb +58 -0
- data/spec/stroke_styles_spec.rb +36 -18
- data/spec/table/span_dummy_spec.rb +17 -0
- data/spec/table_spec.rb +697 -105
- data/spec/template_spec.rb +108 -54
- data/spec/text_at_spec.rb +18 -17
- data/spec/text_box_spec.rb +111 -62
- data/spec/text_rendering_mode_spec.rb +5 -5
- data/spec/text_spacing_spec.rb +4 -4
- data/spec/text_spec.rb +57 -49
- data/spec/transparency_spec.rb +5 -5
- metadata +421 -213
- 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/rails.dat +0 -0
- data/data/images/rails.png +0 -0
- data/examples/bounding_box/russian_boxes.rb +0 -37
- data/examples/example_helper.rb +0 -11
- data/examples/general/context_sensitive_headers.rb +0 -38
- data/examples/graphics/cmyk.rb +0 -13
- data/examples/graphics/gradient.rb +0 -23
- data/examples/graphics/png_types.rb +0 -23
- data/examples/graphics/remote_images.rb +0 -13
- data/examples/m17n/full_win_ansi_character_list.rb +0 -20
- data/examples/m17n/sjis.rb +0 -29
- data/examples/table/bill.rb +0 -54
- data/examples/table/header.rb +0 -15
- data/examples/text/font_calculations.rb +0 -92
- data/examples/text/hyphenation.rb +0 -45
- data/examples/text/indent_paragraphs.rb +0 -24
- data/lib/prawn/core.rb +0 -85
- data/lib/prawn/core/text/formatted/arranger.rb +0 -294
- data/lib/prawn/core/text/formatted/line_wrap.rb +0 -273
- data/lib/prawn/core/text/formatted/wrap.rb +0 -153
- data/lib/prawn/graphics/gradient.rb +0 -84
- data/lib/prawn/security/arcfour.rb +0 -51
@@ -13,8 +13,7 @@ module Prawn
|
|
13
13
|
module Formatted
|
14
14
|
|
15
15
|
class Parser
|
16
|
-
|
17
|
-
def self.to_array(string)
|
16
|
+
PARSER_REGEX = begin
|
18
17
|
regex_string = "\n|" +
|
19
18
|
"<b>|</b>|" +
|
20
19
|
"<i>|</i>|" +
|
@@ -29,8 +28,11 @@ module Prawn
|
|
29
28
|
"<em>|</em>|" +
|
30
29
|
"<a[^>]*>|</a>|" +
|
31
30
|
"[^<\n]+"
|
32
|
-
|
33
|
-
|
31
|
+
Regexp.new(regex_string, Regexp::MULTILINE)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.format(string, *args)
|
35
|
+
tokens = string.gsub(/<br\s*\/?>/, "\n").scan(PARSER_REGEX)
|
34
36
|
self.array_from_tokens(tokens)
|
35
37
|
end
|
36
38
|
|
@@ -122,10 +124,11 @@ module Prawn
|
|
122
124
|
colors = []
|
123
125
|
link = nil
|
124
126
|
anchor = nil
|
127
|
+
local = nil
|
125
128
|
fonts = []
|
126
129
|
sizes = []
|
127
130
|
character_spacings = []
|
128
|
-
|
131
|
+
|
129
132
|
while token = tokens.shift
|
130
133
|
case token
|
131
134
|
when "<b>", "<strong>"
|
@@ -155,6 +158,7 @@ module Prawn
|
|
155
158
|
when "</link>", "</a>"
|
156
159
|
link = nil
|
157
160
|
anchor = nil
|
161
|
+
local = nil
|
158
162
|
when "</color>"
|
159
163
|
colors.pop
|
160
164
|
when "</font>"
|
@@ -168,6 +172,9 @@ module Prawn
|
|
168
172
|
|
169
173
|
matches = /anchor="([^"]*)"/.match(token) || /anchor='([^']*)'/.match(token)
|
170
174
|
anchor = matches[1] unless matches.nil?
|
175
|
+
|
176
|
+
matches = /local="([^"]*)"/.match(token) || /local='([^']*)'/.match(token)
|
177
|
+
local = matches[1] unless matches.nil?
|
171
178
|
elsif token =~ /^<color[^>]*>$/
|
172
179
|
matches = /rgb="#?([^"]*)"/.match(token) || /rgb='#?([^']*)'/.match(token)
|
173
180
|
colors << matches[1] if matches
|
@@ -179,7 +186,7 @@ module Prawn
|
|
179
186
|
# intend to support rgb="#ffffff" or rgb='#ffffff',
|
180
187
|
# r="255" g="255" b="255" or r='255' g='255' b='255',
|
181
188
|
# and c="100" m="100" y="100" k="100" or
|
182
|
-
# c='100' m='100' y='100' k='100'
|
189
|
+
# c='100' m='100' y='100' k='100'
|
183
190
|
# color = { :rgb => "#ffffff" }
|
184
191
|
# color = { :r => 255, :g => 255, :b => 255 }
|
185
192
|
# color = { :c => 100, :m => 100, :y => 100, :k => 100 }
|
@@ -197,6 +204,7 @@ module Prawn
|
|
197
204
|
array << { :text => string,
|
198
205
|
:styles => styles.dup,
|
199
206
|
:color => colors.last,
|
207
|
+
:local => local,
|
200
208
|
:link => link,
|
201
209
|
:anchor => anchor,
|
202
210
|
:font => fonts.last,
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require_relative "line_wrap"
|
2
|
+
require_relative "arranger"
|
3
|
+
|
4
|
+
module Prawn
|
5
|
+
module Text
|
6
|
+
module Formatted #:nodoc:
|
7
|
+
module Wrap #:nodoc:
|
8
|
+
|
9
|
+
def initialize(array, options)
|
10
|
+
@line_wrap = Prawn::Text::Formatted::LineWrap.new
|
11
|
+
@arranger = Prawn::Text::Formatted::Arranger.new(@document,
|
12
|
+
:kerning => options[:kerning])
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
# See the developer documentation for PDF::Core::Text#wrap
|
17
|
+
#
|
18
|
+
# Formatted#wrap should set the following variables:
|
19
|
+
# <tt>@line_height</tt>::
|
20
|
+
# the height of the tallest fragment in the last printed line
|
21
|
+
# <tt>@descender</tt>::
|
22
|
+
# the descender height of the tallest fragment in the last
|
23
|
+
# printed line
|
24
|
+
# <tt>@ascender</tt>::
|
25
|
+
# the ascender heigth of the tallest fragment in the last
|
26
|
+
# printed line
|
27
|
+
# <tt>@baseline_y</tt>::
|
28
|
+
# the baseline of the current line
|
29
|
+
# <tt>@nothing_printed</tt>::
|
30
|
+
# set to true until something is printed, then false
|
31
|
+
# <tt>@everything_printed</tt>::
|
32
|
+
# set to false until everything printed, then true
|
33
|
+
#
|
34
|
+
# Returns any formatted text that was not printed
|
35
|
+
#
|
36
|
+
def wrap(array) #:nodoc:
|
37
|
+
initialize_wrap(array)
|
38
|
+
|
39
|
+
stop = false
|
40
|
+
while !stop
|
41
|
+
# wrap before testing if enough height for this line because the
|
42
|
+
# height of the highest fragment on this line will be used to
|
43
|
+
# determine the line height
|
44
|
+
@line_wrap.wrap_line(:document => @document,
|
45
|
+
:kerning => @kerning,
|
46
|
+
:width => available_width,
|
47
|
+
:arranger => @arranger)
|
48
|
+
|
49
|
+
if enough_height_for_this_line?
|
50
|
+
move_baseline_down
|
51
|
+
print_line
|
52
|
+
else
|
53
|
+
stop = true
|
54
|
+
end
|
55
|
+
|
56
|
+
stop ||= @single_line || @arranger.finished?
|
57
|
+
end
|
58
|
+
@text = @printed_lines.join("\n")
|
59
|
+
@everything_printed = @arranger.finished?
|
60
|
+
@arranger.unconsumed
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def print_line
|
66
|
+
@nothing_printed = false
|
67
|
+
printed_fragments = []
|
68
|
+
fragments_this_line = []
|
69
|
+
|
70
|
+
word_spacing = word_spacing_for_this_line
|
71
|
+
while fragment = @arranger.retrieve_fragment
|
72
|
+
fragment.word_spacing = word_spacing
|
73
|
+
if fragment.text == "\n"
|
74
|
+
printed_fragments << "\n" if @printed_lines.last == ""
|
75
|
+
break
|
76
|
+
end
|
77
|
+
printed_fragments << fragment.text
|
78
|
+
fragments_this_line << fragment
|
79
|
+
end
|
80
|
+
|
81
|
+
accumulated_width = 0
|
82
|
+
fragments_this_line.reverse! if @direction == :rtl
|
83
|
+
fragments_this_line.each do |fragment_this_line|
|
84
|
+
fragment_this_line.default_direction = @direction
|
85
|
+
format_and_draw_fragment(fragment_this_line, accumulated_width,
|
86
|
+
@line_wrap.width, word_spacing)
|
87
|
+
accumulated_width += fragment_this_line.width
|
88
|
+
end
|
89
|
+
|
90
|
+
if "".respond_to?(:force_encoding)
|
91
|
+
printed_fragments.map! { |s| s.force_encoding("utf-8") }
|
92
|
+
end
|
93
|
+
@printed_lines << printed_fragments.join
|
94
|
+
end
|
95
|
+
|
96
|
+
def word_spacing_for_this_line
|
97
|
+
if @align == :justify &&
|
98
|
+
@line_wrap.space_count > 0 &&
|
99
|
+
!@line_wrap.paragraph_finished?
|
100
|
+
(available_width - @line_wrap.width) / @line_wrap.space_count
|
101
|
+
else
|
102
|
+
0
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def enough_height_for_this_line?
|
107
|
+
@line_height = @arranger.max_line_height
|
108
|
+
@descender = @arranger.max_descender
|
109
|
+
@ascender = @arranger.max_ascender
|
110
|
+
if @baseline_y == 0
|
111
|
+
diff = @ascender + @descender
|
112
|
+
else
|
113
|
+
diff = @descender + @line_height + @leading
|
114
|
+
end
|
115
|
+
require_relatived_total_height = @baseline_y.abs + diff
|
116
|
+
if require_relatived_total_height > @height + 0.0001
|
117
|
+
# no room for the full height of this line
|
118
|
+
@arranger.repack_unretrieved
|
119
|
+
false
|
120
|
+
else
|
121
|
+
true
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def initialize_wrap(array)
|
126
|
+
@text = nil
|
127
|
+
@arranger.format_array = array
|
128
|
+
|
129
|
+
# these values will depend on the maximum value within a given line
|
130
|
+
@line_height = 0
|
131
|
+
@descender = 0
|
132
|
+
@ascender = 0
|
133
|
+
@baseline_y = 0
|
134
|
+
|
135
|
+
@printed_lines = []
|
136
|
+
@nothing_printed = true
|
137
|
+
@everything_printed = false
|
138
|
+
end
|
139
|
+
|
140
|
+
def format_and_draw_fragment(fragment, accumulated_width,
|
141
|
+
line_width, word_spacing)
|
142
|
+
@arranger.apply_color_and_font_settings(fragment) do
|
143
|
+
draw_fragment(fragment, accumulated_width,
|
144
|
+
line_width, word_spacing)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# utilities.rb : General-purpose utility classes which don't fit anywhere else
|
4
|
+
#
|
5
|
+
# Copyright August 2012, Alex Dowad. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
|
9
|
+
require 'thread'
|
10
|
+
|
11
|
+
module Prawn
|
12
|
+
|
13
|
+
# Throughout the Prawn codebase, repeated calculations which can benefit from caching are made
|
14
|
+
# In some cases, caching and reusing results can not only save CPU cycles but also greatly
|
15
|
+
# reduce memory requirements
|
16
|
+
# But at the same time, we don't want to throw away thread safety
|
17
|
+
# We have two interchangeable thread-safe cache implementations:
|
18
|
+
|
19
|
+
class SynchronizedCache
|
20
|
+
# As an optimization, this could access the hash directly on VMs with a global interpreter lock (like MRI)
|
21
|
+
def initialize
|
22
|
+
@cache = {}
|
23
|
+
@mutex = Mutex.new
|
24
|
+
end
|
25
|
+
def [](key)
|
26
|
+
@mutex.synchronize { @cache[key] }
|
27
|
+
end
|
28
|
+
def []=(key,value)
|
29
|
+
@mutex.synchronize { @cache[key] = value }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ThreadLocalCache
|
34
|
+
def initialize
|
35
|
+
@cache_id = "cache_#{self.object_id}".to_sym
|
36
|
+
end
|
37
|
+
def [](key)
|
38
|
+
(Thread.current[@cache_id] ||= {})[key]
|
39
|
+
end
|
40
|
+
def []=(key,value)
|
41
|
+
(Thread.current[@cache_id] ||= {})[key] = value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# A PDF document is a collection of pages. When we create a new document be it
|
4
|
+
# with <code>Document.new</code> or on a <code>Document.generate</code> block
|
5
|
+
# one initial page is created for us.
|
6
|
+
#
|
7
|
+
# Some methods might create new pages automatically like <code>text</code> which
|
8
|
+
# will create a new page whenever the text string cannot fit on the current
|
9
|
+
# page.
|
10
|
+
#
|
11
|
+
# But what if you want to go to the next page by yourself? That is easy.
|
12
|
+
#
|
13
|
+
# Just use the <code>start_new_page</code> method and a shiny new page will be
|
14
|
+
# created for you just like in the following snippet.
|
15
|
+
#
|
16
|
+
require File.expand_path(File.join(File.dirname(__FILE__),
|
17
|
+
%w[.. example_helper]))
|
18
|
+
|
19
|
+
filename = File.basename(__FILE__).gsub('.rb', '.pdf')
|
20
|
+
Prawn::Example.generate(filename) do
|
21
|
+
text "We are still on the initial page for this example. Now I'll ask " +
|
22
|
+
"Prawn to gently start a new page. Please follow me to the next page."
|
23
|
+
|
24
|
+
start_new_page
|
25
|
+
|
26
|
+
text "See. We've left the previous page behind."
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Examples for Prawn basic concepts.
|
4
|
+
#
|
5
|
+
require File.expand_path(File.join(File.dirname(__FILE__),
|
6
|
+
%w[.. example_helper]))
|
7
|
+
|
8
|
+
Prawn::Example.generate("basic_concepts.pdf", :page_size => "FOLIO") do
|
9
|
+
|
10
|
+
package "basic_concepts" do |p|
|
11
|
+
|
12
|
+
p.example "creation", :eval_source => false, :full_source => true
|
13
|
+
p.example "origin"
|
14
|
+
p.example "cursor"
|
15
|
+
p.example "other_cursor_helpers"
|
16
|
+
p.example "adding_pages"
|
17
|
+
p.example "measurement"
|
18
|
+
|
19
|
+
p.intro do
|
20
|
+
prose("This chapter covers the minimum amount of functionality you'll need to start using Prawn.
|
21
|
+
|
22
|
+
If you are new to Prawn this is the first chapter to read. Once you are comfortable with the concepts shown here you might want to check the Basics section of the Graphics, Bounding Box and Text sections.
|
23
|
+
|
24
|
+
The examples show:")
|
25
|
+
|
26
|
+
list( "How to create new pdf documents in every possible way",
|
27
|
+
"Where the origin for the document coordinates is. What are Bounding Boxes and how they interact with the origin",
|
28
|
+
"How the cursor behaves",
|
29
|
+
"How to start new pages",
|
30
|
+
"What the base unit for measurement and coordinates is and how to use other convenient measures"
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# There are three ways to create a PDF Document in Prawn: creating a new
|
4
|
+
# <code>Prawn::Document</code> instance, or using the
|
5
|
+
# <code>Prawn::Document.generate</code> method with and without block arguments.
|
6
|
+
#
|
7
|
+
# The following snippet showcase each way by creating a simple document with
|
8
|
+
# some text drawn.
|
9
|
+
#
|
10
|
+
# When we instantiate the <code>Prawn::Document</code> object the actual pdf
|
11
|
+
# document will only be created after we call <code>render_file</code>.
|
12
|
+
#
|
13
|
+
# The generate method will render the actual pdf object after exiting the block.
|
14
|
+
# When we use it without a block argument the provided block is evaluated in the
|
15
|
+
# context of a newly created <code>Prawn::Document</code> instance. When we use
|
16
|
+
# it with a block argument a <code>Prawn::Document</code> instance is created
|
17
|
+
# and passed to the block.
|
18
|
+
#
|
19
|
+
# The generate method without block arguments requires
|
20
|
+
# less typing and defines and renders the pdf document in one shot.
|
21
|
+
# Almost all of the examples are coded this way.
|
22
|
+
#
|
23
|
+
require File.expand_path(File.join(File.dirname(__FILE__),
|
24
|
+
%w[.. example_helper]))
|
25
|
+
|
26
|
+
# Assignment
|
27
|
+
pdf = Prawn::Document.new
|
28
|
+
pdf.text "Hello World"
|
29
|
+
pdf.render_file "assignment.pdf"
|
30
|
+
|
31
|
+
# Implicit Block
|
32
|
+
Prawn::Document.generate("implicit.pdf") do
|
33
|
+
text "Hello World"
|
34
|
+
end
|
35
|
+
|
36
|
+
# Explicit Block
|
37
|
+
Prawn::Document.generate("explicit.pdf") do |pdf|
|
38
|
+
pdf.text "Hello World"
|
39
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# We normally write our documents from top to bottom and it is no different with
|
4
|
+
# Prawn. Even if the origin is on the bottom left corner we still fill the page
|
5
|
+
# from the top to the bottom. In other words the cursor for inserting content
|
6
|
+
# starts on the top of the page.
|
7
|
+
#
|
8
|
+
# Most of the functions that insert content on the page will start at the
|
9
|
+
# current cursor position and proceed to the bottom of the page.
|
10
|
+
#
|
11
|
+
# The following snippet shows how the cursor behaves when we add some text to
|
12
|
+
# the page and demonstrates some of the helpers to manage the cursor position.
|
13
|
+
# The <code>cursor</code> method returns the current cursor position.
|
14
|
+
#
|
15
|
+
require File.expand_path(File.join(File.dirname(__FILE__),
|
16
|
+
%w[.. example_helper]))
|
17
|
+
|
18
|
+
filename = File.basename(__FILE__).gsub('.rb', '.pdf')
|
19
|
+
Prawn::Example.generate(filename) do
|
20
|
+
stroke_axis
|
21
|
+
|
22
|
+
text "the cursor is here: #{cursor}"
|
23
|
+
text "now it is here: #{cursor}"
|
24
|
+
|
25
|
+
move_down 200
|
26
|
+
text "on the first move the cursor went down to: #{cursor}"
|
27
|
+
|
28
|
+
move_up 100
|
29
|
+
text "on the second move the cursor went up to: #{cursor}"
|
30
|
+
|
31
|
+
move_cursor_to 50
|
32
|
+
text "on the last move the cursor went directly to: #{cursor}"
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# The base unit in Prawn is the PDF Point. One PDF Point is equal to 1/72 of
|
4
|
+
# an inch.
|
5
|
+
#
|
6
|
+
# There is no need to waste time converting this measures. Prawn provides
|
7
|
+
# helpers for converting from other measurements
|
8
|
+
# to PDF Points.
|
9
|
+
#
|
10
|
+
# Just <code>require "prawn/measurement_extensions"</code> and it will mix some
|
11
|
+
# helpers onto <code>Numeric</code> for converting common measurement units to
|
12
|
+
# PDF Points.
|
13
|
+
#
|
14
|
+
require File.expand_path(File.join(File.dirname(__FILE__),
|
15
|
+
%w[.. example_helper]))
|
16
|
+
|
17
|
+
filename = File.basename(__FILE__).gsub('.rb', '.pdf')
|
18
|
+
Prawn::Example.generate(filename) do
|
19
|
+
require "prawn/measurement_extensions"
|
20
|
+
|
21
|
+
[:mm, :cm, :dm, :m, :in, :yd, :ft].each do |measurement|
|
22
|
+
text "1 #{measurement} in PDF Points: #{1.send(measurement)} pt"
|
23
|
+
move_down 5.mm
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This is the most important concept you need to learn about Prawn:
|
4
|
+
#
|
5
|
+
# PDF documents have the origin <code>[0,0]</code> at the bottom-left corner of
|
6
|
+
# the page.
|
7
|
+
#
|
8
|
+
# A bounding box is a structure which provides boundaries for inserting content.
|
9
|
+
# A bounding box also has the property of relocating the origin to its relative
|
10
|
+
# bottom-left corner. However, be aware that the location specified when
|
11
|
+
# creating a bounding box is its top-left corner, not bottom-left (hence the
|
12
|
+
# <code>[100, 300]</code> coordinates below).
|
13
|
+
#
|
14
|
+
# Even if you never create a bounding box explictly, each document already comes
|
15
|
+
# with one called the margin box. This initial bounding box is the one
|
16
|
+
# responsible for the document margins.
|
17
|
+
#
|
18
|
+
# So practically speaking the origin of a page on a default generated document
|
19
|
+
# isn't the absolute bottom left corner but the bottom left corner of the margin
|
20
|
+
# box.
|
21
|
+
#
|
22
|
+
# The following snippet strokes a circle on the margin box origin. Then strokes
|
23
|
+
# the boundaries of a bounding box and a circle on its origin.
|
24
|
+
#
|
25
|
+
require File.expand_path(File.join(File.dirname(__FILE__),
|
26
|
+
%w[.. example_helper]))
|
27
|
+
|
28
|
+
filename = File.basename(__FILE__).gsub('.rb', '.pdf')
|
29
|
+
Prawn::Example.generate(filename) do
|
30
|
+
stroke_axis
|
31
|
+
|
32
|
+
stroke_circle [0, 0], 10
|
33
|
+
|
34
|
+
bounding_box([100, 300], :width => 300, :height => 200) do
|
35
|
+
stroke_bounds
|
36
|
+
stroke_circle [0, 0], 10
|
37
|
+
end
|
38
|
+
end
|