prawn 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +3 -4
- data/lib/prawn.rb +3 -6
- data/lib/prawn/document.rb +8 -27
- data/lib/prawn/document/internals.rb +28 -145
- data/lib/prawn/font.rb +2 -23
- data/lib/prawn/font/ttf.rb +1 -1
- data/lib/prawn/graphics.rb +12 -12
- data/lib/prawn/graphics/cap_style.rb +1 -1
- data/lib/prawn/graphics/color.rb +3 -3
- data/lib/prawn/graphics/dash.rb +1 -1
- data/lib/prawn/graphics/join_style.rb +1 -1
- data/lib/prawn/graphics/patterns.rb +1 -1
- data/lib/prawn/graphics/transformation.rb +1 -1
- data/lib/prawn/graphics/transparency.rb +2 -2
- data/lib/prawn/grid.rb +5 -5
- data/lib/prawn/images.rb +2 -2
- data/lib/prawn/security.rb +1 -1
- data/lib/prawn/soft_mask.rb +3 -3
- data/lib/prawn/stamp.rb +1 -1
- data/lib/prawn/text.rb +8 -0
- data/lib/prawn/text/formatted/fragment.rb +19 -8
- data/lib/prawn/version.rb +5 -0
- data/lib/prawn/view.rb +91 -0
- data/manual/basic_concepts/basic_concepts.rb +3 -1
- data/manual/basic_concepts/view.rb +42 -0
- data/prawn.gemspec +9 -4
- data/spec/document_spec.rb +14 -19
- data/spec/graphics_spec.rb +11 -11
- data/spec/line_wrap_spec.rb +10 -7
- data/spec/view_spec.rb +43 -0
- metadata +25 -8
- data/VERSION +0 -1
- data/lib/prawn/document/graphics_state.rb +0 -73
data/lib/prawn/graphics/color.rb
CHANGED
@@ -151,7 +151,7 @@ module Prawn
|
|
151
151
|
raise ArgumentError, "unknown type '#{type}'"
|
152
152
|
end
|
153
153
|
|
154
|
-
add_content "/#{color_space} #{operator}"
|
154
|
+
renderer.add_content "/#{color_space} #{operator}"
|
155
155
|
end
|
156
156
|
|
157
157
|
def set_color(type, color, options = {})
|
@@ -166,7 +166,7 @@ module Prawn
|
|
166
166
|
|
167
167
|
if options[:pattern]
|
168
168
|
set_color_space type, :Pattern
|
169
|
-
add_content "/#{color} #{operator}"
|
169
|
+
renderer.add_content "/#{color} #{operator}"
|
170
170
|
else
|
171
171
|
set_color_space type, color_space(color)
|
172
172
|
color = color_to_s(color)
|
@@ -223,7 +223,7 @@ module Prawn
|
|
223
223
|
end
|
224
224
|
|
225
225
|
def write_color(color, operator)
|
226
|
-
add_content "#{color} #{operator}"
|
226
|
+
renderer.add_content "#{color} #{operator}"
|
227
227
|
end
|
228
228
|
|
229
229
|
end
|
data/lib/prawn/graphics/dash.rb
CHANGED
@@ -145,7 +145,7 @@ module Prawn
|
|
145
145
|
def transformation_matrix(a, b, c, d, e, f)
|
146
146
|
values = [a, b, c, d, e, f].map { |x| "%.5f" % x }.join(" ")
|
147
147
|
save_graphics_state if block_given?
|
148
|
-
add_content "#{values} cm"
|
148
|
+
renderer.add_content "#{values} cm"
|
149
149
|
if block_given?
|
150
150
|
yield
|
151
151
|
restore_graphics_state
|
@@ -54,13 +54,13 @@ module Prawn
|
|
54
54
|
# end
|
55
55
|
#
|
56
56
|
def transparent(opacity, stroke_opacity=opacity, &block)
|
57
|
-
min_version(1.4)
|
57
|
+
renderer.min_version(1.4)
|
58
58
|
|
59
59
|
opacity = [[opacity, 0.0].max, 1.0].min
|
60
60
|
stroke_opacity = [[stroke_opacity, 0.0].max, 1.0].min
|
61
61
|
|
62
62
|
save_graphics_state
|
63
|
-
add_content "/#{opacity_dictionary_name(opacity, stroke_opacity)} gs"
|
63
|
+
renderer.add_content "/#{opacity_dictionary_name(opacity, stroke_opacity)} gs"
|
64
64
|
yield
|
65
65
|
restore_graphics_state
|
66
66
|
end
|
data/lib/prawn/grid.rb
CHANGED
@@ -28,7 +28,7 @@ module Prawn
|
|
28
28
|
# or work with the grid system directly.
|
29
29
|
#
|
30
30
|
# @pdf.grid # Get the Grid directly
|
31
|
-
# @pdf.grid([0,1]) # Get the
|
31
|
+
# @pdf.grid([0,1]) # Get the GridBox at [0,1]
|
32
32
|
# @pdf.grid([0,1], [1,2]) # Get a multi-box spanning from [0,1] to [1,2]
|
33
33
|
#
|
34
34
|
def grid(*args)
|
@@ -49,7 +49,7 @@ module Prawn
|
|
49
49
|
# A Grid represents the entire grid system of a Page and calculates
|
50
50
|
# the column width and row height of the base box.
|
51
51
|
#
|
52
|
-
# @
|
52
|
+
# @group Experimental API
|
53
53
|
class Grid
|
54
54
|
attr_reader :pdf, :columns, :rows, :gutter, :row_gutter, :column_gutter
|
55
55
|
def initialize(pdf, options = {}) # :nodoc:
|
@@ -103,7 +103,7 @@ module Prawn
|
|
103
103
|
# A Grid object has methods that allow easy access to the coordinates of
|
104
104
|
# its corners, which can be plugged into most existing prawnmethods.
|
105
105
|
#
|
106
|
-
# @
|
106
|
+
# @group Experimental API
|
107
107
|
class GridBox
|
108
108
|
attr_reader :pdf
|
109
109
|
|
@@ -206,8 +206,8 @@ module Prawn
|
|
206
206
|
|
207
207
|
# A MultiBox is specified by 2 Boxes and spans the areas between.
|
208
208
|
#
|
209
|
-
# @
|
210
|
-
class MultiBox < GridBox
|
209
|
+
# @group Experimental API
|
210
|
+
class MultiBox < GridBox
|
211
211
|
def initialize(pdf, b1, b2)
|
212
212
|
@pdf = pdf
|
213
213
|
@bs = [b1, b2]
|
data/lib/prawn/images.rb
CHANGED
@@ -89,7 +89,7 @@ module Prawn
|
|
89
89
|
info = Prawn.image_handler.find(image_content).new(image_content)
|
90
90
|
|
91
91
|
# Bump PDF version if the image requires it
|
92
|
-
min_version(info.min_pdf_version) if info.respond_to?(:min_pdf_version)
|
92
|
+
renderer.min_version(info.min_pdf_version) if info.respond_to?(:min_pdf_version)
|
93
93
|
|
94
94
|
# Add the image to the PDF and register it in case we see it again.
|
95
95
|
image_obj = info.build_pdf_object(self)
|
@@ -123,7 +123,7 @@ module Prawn
|
|
123
123
|
|
124
124
|
# add the image to the current page
|
125
125
|
instruct = "\nq\n%.3f 0 0 %.3f %.3f %.3f cm\n/%s Do\nQ"
|
126
|
-
add_content instruct % [ w, h, x, y - h, label ]
|
126
|
+
renderer.add_content instruct % [ w, h, x, y - h, label ]
|
127
127
|
end
|
128
128
|
|
129
129
|
private
|
data/lib/prawn/security.rb
CHANGED
data/lib/prawn/soft_mask.rb
CHANGED
@@ -29,7 +29,7 @@ module Prawn
|
|
29
29
|
# @group Stable API
|
30
30
|
|
31
31
|
def soft_mask(&block)
|
32
|
-
min_version(1.4)
|
32
|
+
renderer.min_version(1.4)
|
33
33
|
|
34
34
|
group_attrs = ref!({
|
35
35
|
:Type => :Group,
|
@@ -73,7 +73,7 @@ module Prawn
|
|
73
73
|
}.hash
|
74
74
|
|
75
75
|
if soft_mask_registry[registry_key]
|
76
|
-
add_content "/#{soft_mask_registry[registry_key]} gs"
|
76
|
+
renderer.add_content "/#{soft_mask_registry[registry_key]} gs"
|
77
77
|
else
|
78
78
|
masks = page.resources[:ExtGState] ||= {}
|
79
79
|
id = masks.empty? ? 'GS1' : masks.keys.sort.last.succ
|
@@ -81,7 +81,7 @@ module Prawn
|
|
81
81
|
|
82
82
|
soft_mask_registry[registry_key] = id
|
83
83
|
|
84
|
-
add_content "/#{id} gs"
|
84
|
+
renderer.add_content "/#{id} gs"
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
data/lib/prawn/stamp.rb
CHANGED
data/lib/prawn/text.rb
CHANGED
@@ -288,6 +288,14 @@ module Prawn
|
|
288
288
|
end
|
289
289
|
end
|
290
290
|
|
291
|
+
# Low level text placement method. All font and size alterations
|
292
|
+
# should already be set
|
293
|
+
#
|
294
|
+
def draw_text!(text, options)
|
295
|
+
x,y = map_to_absolute(options[:at])
|
296
|
+
add_text_content(text,x,y,options)
|
297
|
+
end
|
298
|
+
|
291
299
|
# Gets height of text in PDF points.
|
292
300
|
# Same options as #text, except as noted.
|
293
301
|
# Not compatible with :indent_paragraphs option
|
@@ -209,9 +209,19 @@ module Prawn
|
|
209
209
|
|
210
210
|
def process_text(text)
|
211
211
|
string = strip_zero_width_spaces(text)
|
212
|
+
|
212
213
|
if exclude_trailing_white_space?
|
213
|
-
string =
|
214
|
+
string = string.rstrip
|
215
|
+
|
216
|
+
if soft_hyphens_need_processing?(string)
|
217
|
+
string = process_soft_hyphens(string[0..-2]) + string[-1..-1]
|
218
|
+
end
|
219
|
+
else
|
220
|
+
if soft_hyphens_need_processing?(string)
|
221
|
+
string = process_soft_hyphens(string)
|
222
|
+
end
|
214
223
|
end
|
224
|
+
|
215
225
|
case direction
|
216
226
|
when :rtl
|
217
227
|
string.reverse
|
@@ -224,19 +234,20 @@ module Prawn
|
|
224
234
|
@format_state[:exclude_trailing_white_space]
|
225
235
|
end
|
226
236
|
|
237
|
+
def soft_hyphens_need_processing?(string)
|
238
|
+
string.length > 0 && normalized_soft_hyphen
|
239
|
+
end
|
240
|
+
|
227
241
|
def normalized_soft_hyphen
|
228
242
|
@format_state[:normalized_soft_hyphen]
|
229
243
|
end
|
230
244
|
|
231
245
|
def process_soft_hyphens(string)
|
232
|
-
if string.
|
233
|
-
|
234
|
-
string.force_encoding(normalized_soft_hyphen.encoding)
|
235
|
-
end
|
236
|
-
string[0..-2].gsub(normalized_soft_hyphen, "") + string[-1..-1]
|
237
|
-
else
|
238
|
-
string
|
246
|
+
if string.encoding != normalized_soft_hyphen.encoding
|
247
|
+
string.force_encoding(normalized_soft_hyphen.encoding)
|
239
248
|
end
|
249
|
+
|
250
|
+
string.gsub(normalized_soft_hyphen, "")
|
240
251
|
end
|
241
252
|
|
242
253
|
def strip_zero_width_spaces(string)
|
data/lib/prawn/view.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# prawn/view.rb : Implements a mixin for Prawn's DSL
|
4
|
+
#
|
5
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
6
|
+
|
7
|
+
module Prawn
|
8
|
+
# This mixin allows you to create modular Prawn code without the
|
9
|
+
# need to create subclasses of Prawn::Document.
|
10
|
+
#
|
11
|
+
# class Greeter
|
12
|
+
# include Prawn::View
|
13
|
+
#
|
14
|
+
# def initialize(name)
|
15
|
+
# @name = name
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def say_hello
|
19
|
+
# text "Hello, #{@name}!"
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# def say_goodbye
|
23
|
+
# font("Courier") do
|
24
|
+
# text "Goodbye, #{@name}!"
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# greeter = Greeter.new("Gregory")
|
30
|
+
#
|
31
|
+
# greeter.say_hello
|
32
|
+
# greeter.say_goodbye
|
33
|
+
#
|
34
|
+
# greeter.save_as("greetings.pdf")
|
35
|
+
#
|
36
|
+
# The short story about why you should use this mixin rather than
|
37
|
+
# creating subclasses of +Prawn::Document+ is that it helps
|
38
|
+
# prevent accidental conflicts between your code and Prawn's
|
39
|
+
# code.
|
40
|
+
#
|
41
|
+
# Here's the slightly longer story...
|
42
|
+
#
|
43
|
+
# By using composition rather than inheritance under the hood, this
|
44
|
+
# mixin allows you to keep your state separate from +Prawn::Document+'s
|
45
|
+
# state, and also will prevent unexpected method name collisions due
|
46
|
+
# to late binding effects.
|
47
|
+
#
|
48
|
+
# This mixin is mostly meant for extending Prawn's functionality
|
49
|
+
# with your own additions, but you can also use it to replace or
|
50
|
+
# wrap existing Prawn methods. Calling +super+ will still work
|
51
|
+
# as expected, and alternatively you can explictly call
|
52
|
+
# +document.some_method+ to delegate to Prawn where needed.
|
53
|
+
module View
|
54
|
+
# @group Experimental API
|
55
|
+
|
56
|
+
# Lazily instantiates a +Prawn::Document+ object.
|
57
|
+
#
|
58
|
+
# You can also redefine this method in your own classes to use
|
59
|
+
# a custom document class.
|
60
|
+
def document
|
61
|
+
@document ||= Prawn::Document.new
|
62
|
+
end
|
63
|
+
|
64
|
+
# Delegates all unhandled calls to object returned by +document+ method.
|
65
|
+
# (which is an instance of Prawn::Document by default)
|
66
|
+
def method_missing(m, *a, &b)
|
67
|
+
return super unless document.respond_to?(m)
|
68
|
+
|
69
|
+
document.send(m, *a, &b)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Syntactic sugar that uses +instance_eval+ under the hood to provide
|
73
|
+
# a block-based DSL.
|
74
|
+
#
|
75
|
+
# greeter.update do
|
76
|
+
# say_hello
|
77
|
+
# say_goodbye
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
def update(&b)
|
81
|
+
instance_eval(&b)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Syntatic sugar that calls +document.render_file+ under the hood.
|
85
|
+
#
|
86
|
+
# greeter.save_as("greetings.pdf")
|
87
|
+
def save_as(filename)
|
88
|
+
document.render_file(filename)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -15,6 +15,7 @@ Prawn::ManualBuilder::Example.generate("basic_concepts.pdf", :page_size => "FOLI
|
|
15
15
|
p.example "other_cursor_helpers"
|
16
16
|
p.example "adding_pages"
|
17
17
|
p.example "measurement"
|
18
|
+
p.example "view", :eval_source => false, :full_source => true
|
18
19
|
|
19
20
|
p.intro do
|
20
21
|
prose("This chapter covers the minimum amount of functionality you'll need to start using Prawn.
|
@@ -27,7 +28,8 @@ Prawn::ManualBuilder::Example.generate("basic_concepts.pdf", :page_size => "FOLI
|
|
27
28
|
"Where the origin for the document coordinates is. What are Bounding Boxes and how they interact with the origin",
|
28
29
|
"How the cursor behaves",
|
29
30
|
"How to start new pages",
|
30
|
-
"What the base unit for measurement and coordinates is and how to use other convenient measures"
|
31
|
+
"What the base unit for measurement and coordinates is and how to use other convenient measures",
|
32
|
+
"How to build custom view objects that use Prawn's DSL"
|
31
33
|
)
|
32
34
|
end
|
33
35
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# To create a custom class that extends Prawn's functionality,
|
4
|
+
# use the <code>Prawn::View</code> mixin. This approach is safer than creating
|
5
|
+
# subclasses of <code>Prawn::Document</code> while being just as convenient.
|
6
|
+
#
|
7
|
+
# By using this mixin, your state will be kept completely separate
|
8
|
+
# from <code>Prawn::Document</code>'s state, and you will avoid accidental method
|
9
|
+
# collisions within <code>Prawn::Document</code>.
|
10
|
+
#
|
11
|
+
# To build custom classes that make use of other custom classes,
|
12
|
+
# you can define a method named <code>document()</code> that returns
|
13
|
+
# any object that acts similar to a <code>Prawn::Document</code>
|
14
|
+
# object. <code>Prawn::View</code> will then direct all delegated
|
15
|
+
# calls to that object instead.
|
16
|
+
|
17
|
+
require_relative "../example_helper"
|
18
|
+
|
19
|
+
class Greeter
|
20
|
+
include Prawn::View
|
21
|
+
|
22
|
+
def initialize(name)
|
23
|
+
@name = name
|
24
|
+
end
|
25
|
+
|
26
|
+
def say_hello
|
27
|
+
text "Hello, #{@name}!"
|
28
|
+
end
|
29
|
+
|
30
|
+
def say_goodbye
|
31
|
+
font("Courier") do
|
32
|
+
text "Goodbye, #{@name}!"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
greeter = Greeter.new("Gregory")
|
38
|
+
|
39
|
+
greeter.say_hello
|
40
|
+
greeter.say_goodbye
|
41
|
+
|
42
|
+
greeter.save_as("greetings.pdf")
|
data/prawn.gemspec
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
basedir = File.expand_path(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require "#{basedir}/lib/prawn/version"
|
4
|
+
|
1
5
|
Gem::Specification.new do |spec|
|
2
6
|
spec.name = "prawn"
|
3
|
-
spec.version =
|
7
|
+
spec.version = Prawn::VERSION
|
4
8
|
spec.platform = Gem::Platform::RUBY
|
5
9
|
spec.summary = "A fast and nimble PDF generator for Ruby"
|
6
10
|
spec.files = Dir.glob("{examples,lib,spec,manual}/**/**/*") +
|
@@ -9,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
9
13
|
["data/shift_jis_text.txt"] +
|
10
14
|
["Rakefile", "prawn.gemspec", "Gemfile",
|
11
15
|
"COPYING", "LICENSE", "GPLv2", "GPLv3",
|
12
|
-
"
|
16
|
+
".yardopts"]
|
13
17
|
spec.require_path = "lib"
|
14
18
|
spec.required_ruby_version = '>= 1.9.3'
|
15
19
|
spec.required_rubygems_version = ">= 1.3.6"
|
@@ -20,8 +24,8 @@ Gem::Specification.new do |spec|
|
|
20
24
|
spec.rubyforge_project = "prawn"
|
21
25
|
spec.licenses = ['RUBY', 'GPL-2', 'GPL-3']
|
22
26
|
|
23
|
-
spec.add_dependency('ttfunk', '~> 1.
|
24
|
-
spec.add_dependency('pdf-core', "~> 0.
|
27
|
+
spec.add_dependency('ttfunk', '~> 1.4.0')
|
28
|
+
spec.add_dependency('pdf-core', "~> 0.4.0")
|
25
29
|
|
26
30
|
spec.add_development_dependency('pdf-inspector', '~> 1.1.0')
|
27
31
|
spec.add_development_dependency('yard')
|
@@ -32,6 +36,7 @@ Gem::Specification.new do |spec|
|
|
32
36
|
spec.add_development_dependency('prawn-manual_builder', ">= 0.2.0")
|
33
37
|
spec.add_development_dependency('pdf-reader', '~>1.2')
|
34
38
|
spec.add_development_dependency('rubocop', '0.20.1')
|
39
|
+
spec.add_development_dependency('code_statistics', '0.2.13')
|
35
40
|
|
36
41
|
spec.homepage = "http://prawn.majesticseacreature.com"
|
37
42
|
spec.description = <<END_DESC
|