prawn 1.0.0.rc2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +9 -0
- data/COPYING +2 -2
- data/Gemfile +8 -15
- data/LICENSE +1 -1
- data/Rakefile +25 -16
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.color +0 -0
- data/data/images/dice.alpha +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/license.md +8 -0
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.color +0 -0
- data/lib/prawn.rb +85 -23
- data/lib/prawn/document.rb +134 -116
- data/lib/prawn/document/bounding_box.rb +33 -4
- data/lib/prawn/document/column_box.rb +18 -6
- data/lib/prawn/document/graphics_state.rb +11 -74
- data/lib/prawn/document/internals.rb +24 -23
- data/lib/prawn/document/span.rb +12 -10
- data/lib/prawn/encoding.rb +8 -9
- data/lib/prawn/errors.rb +13 -32
- data/lib/prawn/font.rb +137 -105
- data/lib/prawn/font/afm.rb +76 -32
- data/lib/prawn/font/dfont.rb +4 -3
- data/lib/prawn/font/ttf.rb +33 -25
- data/lib/prawn/font_metric_cache.rb +47 -0
- data/lib/prawn/graphics.rb +177 -57
- data/lib/prawn/graphics/cap_style.rb +4 -3
- data/lib/prawn/graphics/color.rb +5 -4
- data/lib/prawn/graphics/dash.rb +53 -31
- data/lib/prawn/graphics/join_style.rb +9 -7
- data/lib/prawn/graphics/patterns.rb +4 -15
- data/lib/prawn/graphics/transformation.rb +10 -9
- data/lib/prawn/graphics/transparency.rb +3 -1
- data/lib/prawn/{layout/grid.rb → grid.rb} +72 -54
- data/lib/prawn/image_handler.rb +42 -0
- data/lib/prawn/images.rb +58 -54
- data/lib/prawn/images/image.rb +6 -22
- data/lib/prawn/images/jpg.rb +20 -14
- data/lib/prawn/images/png.rb +58 -121
- data/lib/prawn/layout.rb +12 -15
- data/lib/prawn/measurement_extensions.rb +10 -6
- data/lib/prawn/measurements.rb +27 -21
- data/lib/prawn/outline.rb +108 -147
- data/lib/prawn/repeater.rb +10 -8
- data/lib/prawn/security.rb +59 -40
- data/lib/prawn/security/arcfour.rb +52 -0
- data/lib/prawn/soft_mask.rb +4 -4
- data/lib/prawn/stamp.rb +5 -3
- data/lib/prawn/table.rb +83 -60
- data/lib/prawn/table/cell.rb +17 -21
- data/lib/prawn/table/cell/image.rb +2 -3
- data/lib/prawn/table/cell/in_table.rb +8 -2
- data/lib/prawn/table/cell/span_dummy.rb +5 -0
- data/lib/prawn/table/cell/subtable.rb +3 -2
- data/lib/prawn/table/cell/text.rb +14 -12
- data/lib/prawn/table/cells.rb +58 -14
- data/lib/prawn/table/column_width_calculator.rb +61 -0
- data/lib/prawn/text.rb +27 -26
- data/lib/prawn/text/box.rb +12 -6
- data/lib/prawn/text/formatted.rb +5 -4
- data/lib/prawn/text/formatted/arranger.rb +290 -0
- data/lib/prawn/text/formatted/box.rb +85 -57
- data/lib/prawn/text/formatted/fragment.rb +11 -11
- data/lib/prawn/text/formatted/line_wrap.rb +266 -0
- data/lib/prawn/text/formatted/parser.rb +11 -4
- data/lib/prawn/text/formatted/wrap.rb +156 -0
- data/lib/prawn/utilities.rb +5 -3
- data/manual/document_and_page_options/document_and_page_options.rb +2 -1
- data/manual/document_and_page_options/metadata.rb +3 -3
- data/manual/document_and_page_options/page_size.rb +2 -2
- data/manual/document_and_page_options/print_scaling.rb +20 -0
- data/manual/example_file.rb +2 -7
- data/manual/example_helper.rb +62 -81
- data/manual/graphics/common_lines.rb +2 -0
- data/manual/graphics/helper.rb +11 -4
- data/manual/graphics/stroke_dash.rb +19 -14
- data/manual/manual/cover.rb +16 -0
- data/manual/manual/manual.rb +1 -5
- data/manual/text/fallback_fonts.rb +4 -4
- data/manual/text/formatted_text.rb +5 -5
- data/manual/text/inline.rb +2 -4
- data/manual/text/registering_families.rb +12 -12
- data/manual/text/single_usage.rb +4 -4
- data/manual/text/text.rb +0 -2
- data/prawn.gemspec +21 -13
- data/spec/acceptance/png.rb +23 -0
- data/spec/annotations_spec.rb +16 -32
- data/spec/bounding_box_spec.rb +22 -5
- data/spec/cell_spec.rb +49 -5
- data/spec/column_box_spec.rb +32 -0
- data/spec/destinations_spec.rb +5 -5
- data/spec/document_spec.rb +112 -118
- data/spec/extensions/encoding_helpers.rb +5 -2
- data/spec/font_metric_cache_spec.rb +52 -0
- data/spec/font_spec.rb +121 -120
- data/spec/formatted_text_arranger_spec.rb +24 -24
- data/spec/formatted_text_box_spec.rb +31 -32
- data/spec/formatted_text_fragment_spec.rb +2 -2
- data/spec/graphics_spec.rb +63 -45
- data/spec/grid_spec.rb +24 -13
- data/spec/image_handler_spec.rb +54 -0
- data/spec/images_spec.rb +34 -21
- data/spec/inline_formatted_text_parser_spec.rb +69 -20
- data/spec/jpg_spec.rb +3 -3
- data/spec/line_wrap_spec.rb +25 -14
- data/spec/measurement_units_spec.rb +5 -5
- data/spec/outline_spec.rb +68 -64
- data/spec/png_spec.rb +15 -18
- data/spec/reference_spec.rb +2 -82
- data/spec/repeater_spec.rb +1 -1
- data/spec/security_spec.rb +41 -9
- data/spec/soft_mask_spec.rb +0 -40
- data/spec/span_spec.rb +6 -11
- data/spec/spec_helper.rb +20 -2
- data/spec/stamp_spec.rb +19 -20
- data/spec/stroke_styles_spec.rb +31 -13
- data/spec/table/span_dummy_spec.rb +17 -0
- data/spec/table_spec.rb +268 -43
- data/spec/text_at_spec.rb +13 -27
- data/spec/text_box_spec.rb +35 -30
- data/spec/text_spec.rb +56 -40
- data/spec/transparency_spec.rb +5 -5
- metadata +214 -217
- data/README.md +0 -98
- 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.dat +0 -0
- data/data/images/barcode_issue.png +0 -0
- data/data/images/dice.dat +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/lib/prawn/compatibility.rb +0 -87
- data/lib/prawn/core.rb +0 -87
- data/lib/prawn/core/annotations.rb +0 -61
- data/lib/prawn/core/byte_string.rb +0 -9
- data/lib/prawn/core/destinations.rb +0 -90
- data/lib/prawn/core/document_state.rb +0 -79
- data/lib/prawn/core/literal_string.rb +0 -16
- data/lib/prawn/core/name_tree.rb +0 -177
- data/lib/prawn/core/object_store.rb +0 -320
- data/lib/prawn/core/page.rb +0 -212
- data/lib/prawn/core/pdf_object.rb +0 -125
- data/lib/prawn/core/reference.rb +0 -119
- data/lib/prawn/core/text.rb +0 -268
- data/lib/prawn/core/text/formatted/arranger.rb +0 -294
- data/lib/prawn/core/text/formatted/line_wrap.rb +0 -288
- data/lib/prawn/core/text/formatted/wrap.rb +0 -153
- data/lib/prawn/document/page_geometry.rb +0 -136
- data/lib/prawn/document/snapshot.rb +0 -89
- data/manual/manual/foreword.rb +0 -13
- data/manual/templates/full_template.rb +0 -23
- data/manual/templates/page_template.rb +0 -47
- data/manual/templates/templates.rb +0 -26
- data/manual/text/group.rb +0 -29
- data/spec/name_tree_spec.rb +0 -112
- data/spec/object_store_spec.rb +0 -170
- data/spec/pdf_object_spec.rb +0 -172
- data/spec/snapshot_spec.rb +0 -186
- data/spec/template_spec.rb +0 -351
@@ -13,6 +13,7 @@ module Prawn
|
|
13
13
|
module Formatted
|
14
14
|
|
15
15
|
class Parser
|
16
|
+
# @group Extension API
|
16
17
|
|
17
18
|
PARSER_REGEX = begin
|
18
19
|
regex_string = "\n|" +
|
@@ -29,10 +30,10 @@ module Prawn
|
|
29
30
|
"<em>|</em>|" +
|
30
31
|
"<a[^>]*>|</a>|" +
|
31
32
|
"[^<\n]+"
|
32
|
-
|
33
|
+
Regexp.new(regex_string, Regexp::MULTILINE)
|
33
34
|
end
|
34
35
|
|
35
|
-
def self.
|
36
|
+
def self.format(string, *args)
|
36
37
|
tokens = string.gsub(/<br\s*\/?>/, "\n").scan(PARSER_REGEX)
|
37
38
|
self.array_from_tokens(tokens)
|
38
39
|
end
|
@@ -125,10 +126,11 @@ module Prawn
|
|
125
126
|
colors = []
|
126
127
|
link = nil
|
127
128
|
anchor = nil
|
129
|
+
local = nil
|
128
130
|
fonts = []
|
129
131
|
sizes = []
|
130
132
|
character_spacings = []
|
131
|
-
|
133
|
+
|
132
134
|
while token = tokens.shift
|
133
135
|
case token
|
134
136
|
when "<b>", "<strong>"
|
@@ -158,6 +160,7 @@ module Prawn
|
|
158
160
|
when "</link>", "</a>"
|
159
161
|
link = nil
|
160
162
|
anchor = nil
|
163
|
+
local = nil
|
161
164
|
when "</color>"
|
162
165
|
colors.pop
|
163
166
|
when "</font>"
|
@@ -171,6 +174,9 @@ module Prawn
|
|
171
174
|
|
172
175
|
matches = /anchor="([^"]*)"/.match(token) || /anchor='([^']*)'/.match(token)
|
173
176
|
anchor = matches[1] unless matches.nil?
|
177
|
+
|
178
|
+
matches = /local="([^"]*)"/.match(token) || /local='([^']*)'/.match(token)
|
179
|
+
local = matches[1] unless matches.nil?
|
174
180
|
elsif token =~ /^<color[^>]*>$/
|
175
181
|
matches = /rgb="#?([^"]*)"/.match(token) || /rgb='#?([^']*)'/.match(token)
|
176
182
|
colors << matches[1] if matches
|
@@ -182,7 +188,7 @@ module Prawn
|
|
182
188
|
# intend to support rgb="#ffffff" or rgb='#ffffff',
|
183
189
|
# r="255" g="255" b="255" or r='255' g='255' b='255',
|
184
190
|
# and c="100" m="100" y="100" k="100" or
|
185
|
-
# c='100' m='100' y='100' k='100'
|
191
|
+
# c='100' m='100' y='100' k='100'
|
186
192
|
# color = { :rgb => "#ffffff" }
|
187
193
|
# color = { :r => 255, :g => 255, :b => 255 }
|
188
194
|
# color = { :c => 100, :m => 100, :y => 100, :k => 100 }
|
@@ -200,6 +206,7 @@ module Prawn
|
|
200
206
|
array << { :text => string,
|
201
207
|
:styles => styles.dup,
|
202
208
|
:color => colors.last,
|
209
|
+
:local => local,
|
203
210
|
:link => link,
|
204
211
|
:anchor => anchor,
|
205
212
|
:font => fonts.last,
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# wrap.rb: Handles text wrapping for for formatted text
|
2
|
+
#
|
3
|
+
# Contributed by Daniel Nelson
|
4
|
+
#
|
5
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
6
|
+
|
7
|
+
require_relative "line_wrap"
|
8
|
+
require_relative "arranger"
|
9
|
+
|
10
|
+
module Prawn
|
11
|
+
module Text
|
12
|
+
module Formatted #:nodoc:
|
13
|
+
# @private
|
14
|
+
|
15
|
+
module Wrap #:nodoc:
|
16
|
+
|
17
|
+
def initialize(array, options)
|
18
|
+
@line_wrap = Prawn::Text::Formatted::LineWrap.new
|
19
|
+
@arranger = Prawn::Text::Formatted::Arranger.new(@document,
|
20
|
+
:kerning => options[:kerning])
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# See the developer documentation for PDF::Core::Text#wrap
|
25
|
+
#
|
26
|
+
# Formatted#wrap should set the following variables:
|
27
|
+
# <tt>@line_height</tt>::
|
28
|
+
# the height of the tallest fragment in the last printed line
|
29
|
+
# <tt>@descender</tt>::
|
30
|
+
# the descender height of the tallest fragment in the last
|
31
|
+
# printed line
|
32
|
+
# <tt>@ascender</tt>::
|
33
|
+
# the ascender heigth of the tallest fragment in the last
|
34
|
+
# printed line
|
35
|
+
# <tt>@baseline_y</tt>::
|
36
|
+
# the baseline of the current line
|
37
|
+
# <tt>@nothing_printed</tt>::
|
38
|
+
# set to true until something is printed, then false
|
39
|
+
# <tt>@everything_printed</tt>::
|
40
|
+
# set to false until everything printed, then true
|
41
|
+
#
|
42
|
+
# Returns any formatted text that was not printed
|
43
|
+
#
|
44
|
+
def wrap(array) #:nodoc:
|
45
|
+
initialize_wrap(array)
|
46
|
+
|
47
|
+
stop = false
|
48
|
+
while !stop
|
49
|
+
# wrap before testing if enough height for this line because the
|
50
|
+
# height of the highest fragment on this line will be used to
|
51
|
+
# determine the line height
|
52
|
+
@line_wrap.wrap_line(:document => @document,
|
53
|
+
:kerning => @kerning,
|
54
|
+
:width => available_width,
|
55
|
+
:arranger => @arranger)
|
56
|
+
|
57
|
+
if enough_height_for_this_line?
|
58
|
+
move_baseline_down
|
59
|
+
print_line
|
60
|
+
else
|
61
|
+
stop = true
|
62
|
+
end
|
63
|
+
|
64
|
+
stop ||= @single_line || @arranger.finished?
|
65
|
+
end
|
66
|
+
@text = @printed_lines.join("\n")
|
67
|
+
@everything_printed = @arranger.finished?
|
68
|
+
@arranger.unconsumed
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def print_line
|
74
|
+
@nothing_printed = false
|
75
|
+
printed_fragments = []
|
76
|
+
fragments_this_line = []
|
77
|
+
|
78
|
+
word_spacing = word_spacing_for_this_line
|
79
|
+
while fragment = @arranger.retrieve_fragment
|
80
|
+
fragment.word_spacing = word_spacing
|
81
|
+
if fragment.text == "\n"
|
82
|
+
printed_fragments << "\n" if @printed_lines.last == ""
|
83
|
+
break
|
84
|
+
end
|
85
|
+
printed_fragments << fragment.text
|
86
|
+
fragments_this_line << fragment
|
87
|
+
end
|
88
|
+
|
89
|
+
accumulated_width = 0
|
90
|
+
fragments_this_line.reverse! if @direction == :rtl
|
91
|
+
fragments_this_line.each do |fragment_this_line|
|
92
|
+
fragment_this_line.default_direction = @direction
|
93
|
+
format_and_draw_fragment(fragment_this_line, accumulated_width,
|
94
|
+
@line_wrap.width, word_spacing)
|
95
|
+
accumulated_width += fragment_this_line.width
|
96
|
+
end
|
97
|
+
|
98
|
+
@printed_lines << printed_fragments.map { |s| s.force_encoding(::Encoding::UTF_8) }.join
|
99
|
+
end
|
100
|
+
|
101
|
+
def word_spacing_for_this_line
|
102
|
+
if @align == :justify &&
|
103
|
+
@line_wrap.space_count > 0 &&
|
104
|
+
!@line_wrap.paragraph_finished?
|
105
|
+
(available_width - @line_wrap.width) / @line_wrap.space_count
|
106
|
+
else
|
107
|
+
0
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def enough_height_for_this_line?
|
112
|
+
@line_height = @arranger.max_line_height
|
113
|
+
@descender = @arranger.max_descender
|
114
|
+
@ascender = @arranger.max_ascender
|
115
|
+
if @baseline_y == 0
|
116
|
+
diff = @ascender + @descender
|
117
|
+
else
|
118
|
+
diff = @descender + @line_height + @leading
|
119
|
+
end
|
120
|
+
require_relatived_total_height = @baseline_y.abs + diff
|
121
|
+
if require_relatived_total_height > @height + 0.0001
|
122
|
+
# no room for the full height of this line
|
123
|
+
@arranger.repack_unretrieved
|
124
|
+
false
|
125
|
+
else
|
126
|
+
true
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def initialize_wrap(array)
|
131
|
+
@text = nil
|
132
|
+
@arranger.format_array = array
|
133
|
+
|
134
|
+
# these values will depend on the maximum value within a given line
|
135
|
+
@line_height = 0
|
136
|
+
@descender = 0
|
137
|
+
@ascender = 0
|
138
|
+
@baseline_y = 0
|
139
|
+
|
140
|
+
@printed_lines = []
|
141
|
+
@nothing_printed = true
|
142
|
+
@everything_printed = false
|
143
|
+
end
|
144
|
+
|
145
|
+
def format_and_draw_fragment(fragment, accumulated_width,
|
146
|
+
line_width, word_spacing)
|
147
|
+
@arranger.apply_color_and_font_settings(fragment) do
|
148
|
+
draw_fragment(fragment, accumulated_width,
|
149
|
+
line_width, word_spacing)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
data/lib/prawn/utilities.rb
CHANGED
@@ -16,7 +16,8 @@ module Prawn
|
|
16
16
|
# But at the same time, we don't want to throw away thread safety
|
17
17
|
# We have two interchangeable thread-safe cache implementations:
|
18
18
|
|
19
|
-
|
19
|
+
# @private
|
20
|
+
class SynchronizedCache
|
20
21
|
# As an optimization, this could access the hash directly on VMs with a global interpreter lock (like MRI)
|
21
22
|
def initialize
|
22
23
|
@cache = {}
|
@@ -29,8 +30,9 @@ module Prawn
|
|
29
30
|
@mutex.synchronize { @cache[key] = value }
|
30
31
|
end
|
31
32
|
end
|
32
|
-
|
33
|
-
|
33
|
+
|
34
|
+
# @private
|
35
|
+
class ThreadLocalCache
|
34
36
|
def initialize
|
35
37
|
@cache_id = "cache_#{self.object_id}".to_sym
|
36
38
|
end
|
@@ -14,7 +14,8 @@ Prawn::Example.generate("document_and_page_options.pdf",
|
|
14
14
|
p.example "page_margins", :eval_source => false, :full_source => true
|
15
15
|
p.example "background", :eval_source => false, :full_source => true
|
16
16
|
p.example "metadata", :eval_source => false, :full_source => true
|
17
|
-
|
17
|
+
p.example "print_scaling",:eval_source => false, :full_source => true
|
18
|
+
|
18
19
|
p.intro do
|
19
20
|
prose("So far we've already seen how to create new documents and start new pages. This chapter expands on the previous examples by showing other options avialable. Some of the options are only available when creating new documents.
|
20
21
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# To set the document metadata just pass a hash to the <code>:info</code>
|
4
4
|
# option when creating new documents.
|
5
|
+
# The keys in the example below are arbitrary, so you may add whatever keys you want
|
5
6
|
#
|
6
7
|
require File.expand_path(File.join(File.dirname(__FILE__),
|
7
8
|
%w[.. example_helper]))
|
@@ -14,10 +15,9 @@ Prawn::Document.generate("metadata.pdf",
|
|
14
15
|
:Keywords => "test metadata ruby pdf dry",
|
15
16
|
:Creator => "ACME Soft App",
|
16
17
|
:Producer => "Prawn",
|
17
|
-
:CreationDate => Time.now
|
18
|
-
:Grok => "Test Property"
|
18
|
+
:CreationDate => Time.now
|
19
19
|
}) do
|
20
20
|
|
21
21
|
text "This is a test of setting metadata properties via the info option."
|
22
|
-
text "
|
22
|
+
text "While the keys are arbitrary, the above example sets common attributes."
|
23
23
|
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
#
|
3
3
|
# Prawn comes with support for most of the common page sizes so you'll only need
|
4
4
|
# to provide specific values if your intended format is not supported. To see a
|
5
|
-
# list with all supported sizes take a look at
|
5
|
+
# list with all supported sizes take a look at PDF::Core::PageGeometry
|
6
6
|
#
|
7
|
-
# To define the size use <code>:page_size</code> when creating new documents
|
7
|
+
# # To define the size use <code>:page_size</code> when creating new documents
|
8
8
|
# and <code>:size</code> when starting new pages. The default page size for new
|
9
9
|
# documents is LETTER (612.00 x 792.00).
|
10
10
|
#
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# (Optional; PDF 1.6) The page scaling option to be selected when a print dialog is displayed for this document.
|
4
|
+
# Valid values are <code>None</code>, which indicates that the print dialog should reflect no page scaling,
|
5
|
+
# and <code>AppDefault</code>, which indicates that applications should use the current print scaling.
|
6
|
+
# If this entry has an unrecognized value, applications should use the current print scaling.
|
7
|
+
# Default value: <code>AppDefault</code>.
|
8
|
+
#
|
9
|
+
# Note: If the print dialog is suppressed and its parameters are provided directly by the application, the value of this entry should still be used.
|
10
|
+
#
|
11
|
+
|
12
|
+
require File.expand_path(File.join(File.dirname(__FILE__),
|
13
|
+
%w[.. example_helper]))
|
14
|
+
|
15
|
+
Prawn::Document.generate("print_scaling.pdf",
|
16
|
+
:page_layout => :landscape,
|
17
|
+
:print_scaling => :none
|
18
|
+
) do
|
19
|
+
text "When you print this document, the scale to fit in print preview should be disabled by default."
|
20
|
+
end
|
data/manual/example_file.rb
CHANGED
@@ -103,13 +103,8 @@ module Prawn
|
|
103
103
|
def read_file(folder_name, filename)
|
104
104
|
data = File.read(File.expand_path(File.join(
|
105
105
|
File.dirname(__FILE__), folder_name, filename)))
|
106
|
-
|
107
|
-
|
108
|
-
# UTF-8, we will need to fix this to work on Ruby 1.9.
|
109
|
-
if data.respond_to?(:encode!)
|
110
|
-
data.encode!("UTF-8")
|
111
|
-
end
|
112
|
-
data
|
106
|
+
|
107
|
+
data.encode(::Encoding::UTF_8)
|
113
108
|
end
|
114
109
|
|
115
110
|
end
|
data/manual/example_helper.rb
CHANGED
@@ -18,7 +18,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'syntax_highlight'))
|
|
18
18
|
Prawn.debug = true
|
19
19
|
|
20
20
|
module Prawn
|
21
|
-
|
21
|
+
|
22
22
|
# The Prawn::Example class holds all the helper methods used to generate the
|
23
23
|
# Prawn by example manual.
|
24
24
|
#
|
@@ -37,22 +37,22 @@ module Prawn
|
|
37
37
|
# whole load of manuals)
|
38
38
|
#
|
39
39
|
class Example < Prawn::Document
|
40
|
-
|
40
|
+
|
41
41
|
# Values used for the manual design:
|
42
|
-
|
42
|
+
|
43
43
|
# This is the default value for the margin box
|
44
44
|
#
|
45
45
|
BOX_MARGIN = 36
|
46
|
-
|
46
|
+
|
47
47
|
# Additional indentation to keep the line measure with a reasonable size
|
48
|
-
#
|
48
|
+
#
|
49
49
|
INNER_MARGIN = 30
|
50
|
-
|
50
|
+
|
51
51
|
# Vertical Rhythm settings
|
52
52
|
#
|
53
53
|
RHYTHM = 10
|
54
54
|
LEADING = 2
|
55
|
-
|
55
|
+
|
56
56
|
# Colors
|
57
57
|
#
|
58
58
|
BLACK = "000000"
|
@@ -64,18 +64,18 @@ module Prawn
|
|
64
64
|
LIGHT_GOLD = "FBFBBE"
|
65
65
|
DARK_GOLD = "EBE389"
|
66
66
|
BLUE = "0000D0"
|
67
|
-
|
67
|
+
|
68
68
|
# Used to generate the url for the example files
|
69
69
|
#
|
70
70
|
MANUAL_URL = "http://github.com/prawnpdf/prawn/tree/master/manual"
|
71
|
-
|
72
|
-
|
71
|
+
|
72
|
+
|
73
73
|
# Loads a package. Used on the manual.
|
74
74
|
#
|
75
75
|
def load_package(package)
|
76
76
|
load_file(package, package)
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
# Loads a page with outline support. Used on the manual.
|
80
80
|
#
|
81
81
|
def load_page(page)
|
@@ -93,8 +93,8 @@ module Prawn
|
|
93
93
|
example = ExampleFile.new(package, "#{file}.rb")
|
94
94
|
eval example.generate_block_source
|
95
95
|
end
|
96
|
-
|
97
|
-
|
96
|
+
|
97
|
+
|
98
98
|
# Creates a new ExamplePackage object and yields it to a block in order for
|
99
99
|
# it to be populated with examples, sections and some introduction text.
|
100
100
|
# Used on the package files.
|
@@ -104,7 +104,7 @@ module Prawn
|
|
104
104
|
ep.instance_eval(&block)
|
105
105
|
ep.render(self)
|
106
106
|
end
|
107
|
-
|
107
|
+
|
108
108
|
# Renders an ExamplePackage cover page.
|
109
109
|
#
|
110
110
|
# Starts a new page and renders the package introduction text.
|
@@ -117,16 +117,16 @@ module Prawn
|
|
117
117
|
section(package.name, :destination => page_number, :closed => true)
|
118
118
|
end
|
119
119
|
end
|
120
|
-
|
120
|
+
|
121
121
|
# Add the ExampleSection to the document outline within the appropriate
|
122
122
|
# package.
|
123
123
|
#
|
124
124
|
def render_section(section)
|
125
|
-
outline.add_subsection_to(section.package_name) do
|
125
|
+
outline.add_subsection_to(section.package_name) do
|
126
126
|
outline.section(section.name, :closed => true)
|
127
127
|
end
|
128
128
|
end
|
129
|
-
|
129
|
+
|
130
130
|
# Renders an ExampleFile.
|
131
131
|
#
|
132
132
|
# Starts a new page and renders an introductory text, the example source and
|
@@ -135,26 +135,26 @@ module Prawn
|
|
135
135
|
#
|
136
136
|
def render_example(example)
|
137
137
|
start_new_page
|
138
|
-
|
139
|
-
outline.add_subsection_to(example.parent_name) do
|
138
|
+
|
139
|
+
outline.add_subsection_to(example.parent_name) do
|
140
140
|
outline.page(:destination => page_number, :title => example.name)
|
141
141
|
end
|
142
|
-
|
142
|
+
|
143
143
|
example_header(example.parent_folder_name, example.filename)
|
144
|
-
|
144
|
+
|
145
145
|
prose(example.introduction_text)
|
146
|
-
|
146
|
+
|
147
147
|
code(example.source)
|
148
|
-
|
148
|
+
|
149
149
|
if example.eval?
|
150
|
-
eval_code(example.source)
|
150
|
+
eval_code(example.source)
|
151
151
|
else
|
152
152
|
source_link(example)
|
153
153
|
end
|
154
|
-
|
154
|
+
|
155
155
|
reset_settings
|
156
156
|
end
|
157
|
-
|
157
|
+
|
158
158
|
# Render the example header. Used on the example pages of the manual
|
159
159
|
#
|
160
160
|
def example_header(package, example)
|
@@ -168,7 +168,7 @@ module Prawn
|
|
168
168
|
end
|
169
169
|
end
|
170
170
|
end
|
171
|
-
|
171
|
+
|
172
172
|
# Register fonts used on the manual
|
173
173
|
#
|
174
174
|
def register_fonts
|
@@ -182,7 +182,7 @@ module Prawn
|
|
182
182
|
:normal => { :file => dejavu_file, :font => "DejaVu" }
|
183
183
|
}
|
184
184
|
end
|
185
|
-
|
185
|
+
|
186
186
|
# Render a block of text after processing code tags and URLs to be used with
|
187
187
|
# the inline_format option.
|
188
188
|
#
|
@@ -190,7 +190,7 @@ module Prawn
|
|
190
190
|
# package pages intro
|
191
191
|
#
|
192
192
|
def prose(str)
|
193
|
-
|
193
|
+
|
194
194
|
# Process the <code> tags
|
195
195
|
str.gsub!(/<code>([^<]+?)<\/code>/,
|
196
196
|
"<font name='Courier'><b>\\1<\/b><\/font>")
|
@@ -198,31 +198,31 @@ module Prawn
|
|
198
198
|
# Process the links
|
199
199
|
str.gsub!(/(https?:\/\/\S+)/,
|
200
200
|
"<color rgb='#{BLUE}'><link href=\"\\1\">\\1</link></color>")
|
201
|
-
|
201
|
+
|
202
202
|
inner_box do
|
203
203
|
font("Helvetica", :size => 11) do
|
204
204
|
str.split(/\n\n+/).each do |paragraph|
|
205
|
-
|
205
|
+
|
206
206
|
text(paragraph.gsub(/\s+/," "),
|
207
207
|
:align => :justify,
|
208
208
|
:inline_format => true,
|
209
209
|
:leading => LEADING,
|
210
210
|
:color => DARK_GRAY)
|
211
|
-
|
211
|
+
|
212
212
|
move_down(RHYTHM)
|
213
213
|
end
|
214
214
|
end
|
215
215
|
end
|
216
|
-
|
216
|
+
|
217
217
|
move_down(RHYTHM)
|
218
218
|
end
|
219
|
-
|
219
|
+
|
220
220
|
# Render a code block. Used on the example pages of the manual
|
221
221
|
#
|
222
222
|
def code(str)
|
223
223
|
pre_text = str.gsub(' ', Prawn::Text::NBSP)
|
224
224
|
pre_text = ::CodeRay.scan(pre_text, :ruby).to_prawn
|
225
|
-
|
225
|
+
|
226
226
|
font('Courier', :size => 9.5) do
|
227
227
|
colored_box(pre_text, :fill_color => DARK_GRAY)
|
228
228
|
end
|
@@ -254,17 +254,17 @@ module Prawn
|
|
254
254
|
#
|
255
255
|
def source_link(example)
|
256
256
|
url = "#{MANUAL_URL}/#{example.parent_folder_name}/#{example.filename}"
|
257
|
-
|
257
|
+
|
258
258
|
reason = [{ :text => "This code snippet was not evaluated inline. " +
|
259
259
|
"You may see its output by running the " +
|
260
260
|
"example file located here:\n",
|
261
261
|
:color => DARK_GRAY },
|
262
|
-
|
262
|
+
|
263
263
|
{ :text => url,
|
264
264
|
:color => BLUE,
|
265
265
|
:link => url}
|
266
266
|
]
|
267
|
-
|
267
|
+
|
268
268
|
font('Helvetica', :size => 9) do
|
269
269
|
colored_box(reason,
|
270
270
|
:fill_color => LIGHT_GOLD,
|
@@ -272,7 +272,7 @@ module Prawn
|
|
272
272
|
:leading => LEADING*3)
|
273
273
|
end
|
274
274
|
end
|
275
|
-
|
275
|
+
|
276
276
|
# Render a page header. Used on the manual lone pages and package
|
277
277
|
# introductory pages
|
278
278
|
#
|
@@ -284,19 +284,19 @@ module Prawn
|
|
284
284
|
end
|
285
285
|
end
|
286
286
|
end
|
287
|
-
|
287
|
+
|
288
288
|
# Render the arguments as a bulleted list. Used on the manual package
|
289
289
|
# introductory pages
|
290
290
|
#
|
291
291
|
def list(*items)
|
292
292
|
move_up(RHYTHM)
|
293
|
-
|
293
|
+
|
294
294
|
inner_box do
|
295
295
|
font("Helvetica", :size => 11) do
|
296
296
|
items.each do |li|
|
297
297
|
float { text("•", :color => DARK_GRAY) }
|
298
298
|
indent(RHYTHM) do
|
299
|
-
text(li.gsub(/\s+/," "),
|
299
|
+
text(li.gsub(/\s+/," "),
|
300
300
|
:inline_format => true,
|
301
301
|
:color => DARK_GRAY,
|
302
302
|
:leading => LEADING)
|
@@ -307,30 +307,30 @@ module Prawn
|
|
307
307
|
end
|
308
308
|
end
|
309
309
|
end
|
310
|
-
|
310
|
+
|
311
311
|
# Renders the page-wide headers
|
312
312
|
#
|
313
313
|
def header_box(&block)
|
314
314
|
bounding_box([-bounds.absolute_left, cursor + BOX_MARGIN],
|
315
315
|
:width => bounds.absolute_left + bounds.absolute_right,
|
316
316
|
:height => BOX_MARGIN*2 + RHYTHM*2) do
|
317
|
-
|
317
|
+
|
318
318
|
fill_color LIGHT_GRAY
|
319
319
|
fill_rectangle([bounds.left, bounds.top],
|
320
320
|
bounds.right,
|
321
321
|
bounds.top - bounds.bottom)
|
322
322
|
fill_color BLACK
|
323
|
-
|
323
|
+
|
324
324
|
indent(BOX_MARGIN + INNER_MARGIN, &block)
|
325
325
|
end
|
326
|
-
|
326
|
+
|
327
327
|
stroke_color GRAY
|
328
328
|
stroke_horizontal_line(-BOX_MARGIN, bounds.width + BOX_MARGIN, :at => cursor)
|
329
329
|
stroke_color BLACK
|
330
|
-
|
330
|
+
|
331
331
|
move_down(RHYTHM*3)
|
332
332
|
end
|
333
|
-
|
333
|
+
|
334
334
|
# Renders a Bounding Box for the inner margin
|
335
335
|
#
|
336
336
|
def inner_box(&block)
|
@@ -338,7 +338,7 @@ module Prawn
|
|
338
338
|
:width => bounds.width - INNER_MARGIN*2,
|
339
339
|
&block)
|
340
340
|
end
|
341
|
-
|
341
|
+
|
342
342
|
# Renders a Bounding Box with some background color and the formatted text
|
343
343
|
# inside it
|
344
344
|
#
|
@@ -348,17 +348,17 @@ module Prawn
|
|
348
348
|
:text_color => LIGHT_GRAY,
|
349
349
|
:leading => LEADING
|
350
350
|
}.merge(options)
|
351
|
-
|
351
|
+
|
352
352
|
register_fonts
|
353
|
-
text_options = { :leading => options[:leading],
|
353
|
+
text_options = { :leading => options[:leading],
|
354
354
|
:fallback_fonts => ["DejaVu", "Kai"]
|
355
355
|
}
|
356
|
-
|
356
|
+
|
357
357
|
box_height = height_of_formatted(box_text, text_options)
|
358
|
-
|
358
|
+
|
359
359
|
bounding_box([INNER_MARGIN + RHYTHM, cursor],
|
360
360
|
:width => bounds.width - (INNER_MARGIN+RHYTHM)*2) do
|
361
|
-
|
361
|
+
|
362
362
|
fill_color options[:fill_color]
|
363
363
|
stroke_color options[:stroke_color] || options[:fill_color]
|
364
364
|
fill_and_stroke_rounded_rectangle(
|
@@ -369,54 +369,35 @@ module Prawn
|
|
369
369
|
)
|
370
370
|
fill_color BLACK
|
371
371
|
stroke_color BLACK
|
372
|
-
|
372
|
+
|
373
373
|
pad(RHYTHM) do
|
374
374
|
formatted_text(box_text, text_options)
|
375
375
|
end
|
376
376
|
end
|
377
|
-
|
377
|
+
|
378
378
|
move_down(RHYTHM*2)
|
379
379
|
end
|
380
|
-
|
380
|
+
|
381
381
|
# Draws X and Y axis rulers beginning at the margin box origin. Used on
|
382
382
|
# examples.
|
383
383
|
#
|
384
384
|
def stroke_axis(options={})
|
385
|
-
|
386
|
-
:width => bounds.width.to_i
|
387
|
-
}.merge(options)
|
388
|
-
|
389
|
-
dash(1, :space => 4)
|
390
|
-
stroke_horizontal_line(-21, options[:width], :at => 0)
|
391
|
-
stroke_vertical_line(-21, options[:height], :at => 0)
|
392
|
-
undash
|
393
|
-
|
394
|
-
fill_circle [0, 0], 1
|
395
|
-
|
396
|
-
(100..options[:width]).step(100) do |point|
|
397
|
-
fill_circle [point, 0], 1
|
398
|
-
draw_text point, :at => [point-5, -10], :size => 7
|
399
|
-
end
|
400
|
-
|
401
|
-
(100..options[:height]).step(100) do |point|
|
402
|
-
fill_circle [0, point], 1
|
403
|
-
draw_text point, :at => [-17, point-2], :size => 7
|
404
|
-
end
|
385
|
+
super({:height => (cursor - 20).to_i}.merge(options))
|
405
386
|
end
|
406
|
-
|
387
|
+
|
407
388
|
# Reset some of the Prawn settings including graphics and text to their
|
408
389
|
# defaults.
|
409
|
-
#
|
390
|
+
#
|
410
391
|
# Used after rendering examples so that each new example starts with a clean
|
411
392
|
# slate.
|
412
393
|
#
|
413
394
|
def reset_settings
|
414
|
-
|
395
|
+
|
415
396
|
# Text settings
|
416
397
|
font("Helvetica", :size => 12)
|
417
398
|
default_leading 0
|
418
399
|
self.text_direction = :ltr
|
419
|
-
|
400
|
+
|
420
401
|
# Graphics settings
|
421
402
|
self.line_width = 1
|
422
403
|
self.cap_style = :butt
|