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