prawn 0.14.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +2 -1
- data/Rakefile +12 -0
- data/lib/prawn.rb +9 -21
- data/lib/prawn/document.rb +95 -68
- data/lib/prawn/document/bounding_box.rb +22 -4
- data/lib/prawn/document/column_box.rb +2 -0
- data/lib/prawn/document/graphics_state.rb +1 -1
- data/lib/prawn/document/internals.rb +2 -2
- data/lib/prawn/document/snapshot.rb +2 -1
- data/lib/prawn/document/span.rb +2 -0
- data/lib/prawn/encoding.rb +1 -1
- data/lib/prawn/font.rb +89 -75
- data/lib/prawn/font/afm.rb +3 -0
- data/lib/prawn/font/dfont.rb +1 -0
- data/lib/prawn/font/ttf.rb +2 -0
- data/lib/prawn/font_metric_cache.rb +3 -1
- data/lib/prawn/graphics.rb +2 -14
- data/lib/prawn/graphics/cap_style.rb +1 -0
- data/lib/prawn/graphics/color.rb +1 -0
- data/lib/prawn/graphics/dash.rb +3 -2
- data/lib/prawn/graphics/join_style.rb +2 -0
- data/lib/prawn/graphics/patterns.rb +1 -0
- data/lib/prawn/graphics/transformation.rb +1 -0
- data/lib/prawn/graphics/transparency.rb +2 -0
- data/lib/prawn/image_handler.rb +2 -0
- data/lib/prawn/images.rb +5 -0
- data/lib/prawn/images/image.rb +1 -0
- data/lib/prawn/images/jpg.rb +3 -0
- data/lib/prawn/images/png.rb +2 -0
- data/lib/prawn/layout.rb +8 -13
- data/lib/prawn/layout/grid.rb +15 -3
- data/lib/prawn/measurement_extensions.rb +4 -0
- data/lib/prawn/measurements.rb +2 -0
- data/lib/prawn/outline.rb +3 -1
- data/lib/prawn/repeater.rb +3 -1
- data/lib/prawn/security.rb +15 -7
- data/lib/prawn/security/arcfour.rb +52 -0
- data/lib/prawn/soft_mask.rb +3 -1
- data/lib/prawn/stamp.rb +2 -0
- data/lib/prawn/table.rb +2 -0
- data/lib/prawn/table/cell.rb +4 -1
- data/lib/prawn/table/cell/image.rb +1 -2
- data/lib/prawn/table/cell/in_table.rb +2 -0
- data/lib/prawn/table/cell/span_dummy.rb +1 -0
- data/lib/prawn/table/cells.rb +7 -2
- data/lib/prawn/table/column_width_calculator.rb +8 -2
- data/lib/prawn/text.rb +4 -2
- data/lib/prawn/text/box.rb +3 -0
- data/lib/prawn/text/formatted/arranger.rb +2 -0
- data/lib/prawn/text/formatted/box.rb +55 -50
- data/lib/prawn/text/formatted/fragment.rb +2 -0
- data/lib/prawn/text/formatted/line_wrap.rb +1 -0
- data/lib/prawn/text/formatted/parser.rb +2 -0
- data/lib/prawn/text/formatted/wrap.rb +2 -0
- data/lib/prawn/utilities.rb +5 -3
- data/manual/graphics/common_lines.rb +2 -0
- data/manual/text/group.rb +2 -0
- data/manual/text/text.rb +1 -1
- data/prawn.gemspec +4 -3
- data/spec/grid_spec.rb +11 -0
- data/spec/object_store_spec.rb +1 -96
- data/spec/reference_spec.rb +0 -57
- data/spec/spec_helper.rb +7 -0
- data/spec/table_spec.rb +26 -0
- metadata +172 -185
- data/lib/pdf/core.rb +0 -35
- data/lib/pdf/core/annotations.rb +0 -60
- data/lib/pdf/core/byte_string.rb +0 -9
- data/lib/pdf/core/destinations.rb +0 -90
- data/lib/pdf/core/document_state.rb +0 -79
- data/lib/pdf/core/filter_list.rb +0 -51
- data/lib/pdf/core/filters.rb +0 -36
- data/lib/pdf/core/graphics_state.rb +0 -89
- data/lib/pdf/core/literal_string.rb +0 -16
- data/lib/pdf/core/name_tree.rb +0 -177
- data/lib/pdf/core/object_store.rb +0 -311
- data/lib/pdf/core/outline.rb +0 -315
- data/lib/pdf/core/page.rb +0 -212
- data/lib/pdf/core/page_geometry.rb +0 -126
- data/lib/pdf/core/pdf_object.rb +0 -99
- data/lib/pdf/core/reference.rb +0 -103
- data/lib/pdf/core/stream.rb +0 -98
- data/lib/pdf/core/text.rb +0 -275
- data/lib/prawn/templates.rb +0 -75
- data/spec/filters_spec.rb +0 -34
- data/spec/name_tree_spec.rb +0 -112
- data/spec/pdf_object_spec.rb +0 -172
- data/spec/stream_spec.rb +0 -58
- data/spec/template_spec_obsolete.rb +0 -352
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97e70822529ce4c7edb736c4c57f2c6a015ddb02
|
4
|
+
data.tar.gz: 685b8386302414f80c7ac7a7c714987e0a8d2ff9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dad2cab43e9fdda28fa1a4c364507fd7ecff16d2120a65b3c8ab9a07130d8c6fd73a6a9ae44a98be6faad680b20e894e9d6d1d8b88a870b824f08b9a5a28e527
|
7
|
+
data.tar.gz: 3c61667b13c7ed6aa815728ec777e8d12b04f7219184682d8b2b37d9fe046c942529c957f35597c3ccfe2a48131c701834d209a5cd77a454be9395e695450be3
|
data/.yardopts
CHANGED
data/Rakefile
CHANGED
@@ -40,3 +40,15 @@ Gem::PackageTask.new(spec) do |pkg|
|
|
40
40
|
pkg.need_zip = true
|
41
41
|
pkg.need_tar = true
|
42
42
|
end
|
43
|
+
|
44
|
+
desc "Run a console with Prawn loaded"
|
45
|
+
task :console do
|
46
|
+
require 'irb'
|
47
|
+
require 'irb/completion'
|
48
|
+
require_relative 'lib/prawn'
|
49
|
+
Prawn.debug = true
|
50
|
+
|
51
|
+
ARGV.clear
|
52
|
+
IRB.start
|
53
|
+
end
|
54
|
+
|
data/lib/prawn.rb
CHANGED
@@ -1,26 +1,13 @@
|
|
1
1
|
# Welcome to Prawn, the best PDF Generation library ever.
|
2
2
|
# This documentation covers user level functionality.
|
3
3
|
#
|
4
|
-
# Those looking to contribute code or write extensions should look
|
5
|
-
# into the lib/prawn/core/* source tree.
|
6
|
-
#
|
7
|
-
%w[ttfunk/lib].each do |dep|
|
8
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__) + "/../../vendor/#{dep}")
|
9
|
-
end
|
10
|
-
|
11
|
-
begin
|
12
|
-
require 'ttfunk'
|
13
|
-
rescue LoadError
|
14
|
-
puts "Failed to load ttfunk. If you are running Prawn from git:"
|
15
|
-
puts " git submodule init"
|
16
|
-
puts " git submodule update"
|
17
|
-
exit
|
18
|
-
end
|
19
|
-
|
20
4
|
require "set"
|
21
5
|
|
6
|
+
require 'ttfunk'
|
7
|
+
require "pdf/core"
|
8
|
+
|
22
9
|
module Prawn
|
23
|
-
VERSION = "0.
|
10
|
+
VERSION = "0.15.0"
|
24
11
|
|
25
12
|
extend self
|
26
13
|
|
@@ -33,6 +20,8 @@ module Prawn
|
|
33
20
|
#
|
34
21
|
BASEDIR = File.expand_path(File.join(dir, '..'))
|
35
22
|
DATADIR = File.expand_path(File.join(dir, '..', 'data'))
|
23
|
+
|
24
|
+
FLOAT_PRECISION = 1.0e-9
|
36
25
|
|
37
26
|
# Whe set to true, Prawn will verify hash options to ensure only valid keys
|
38
27
|
# are used. Off by default.
|
@@ -43,9 +32,9 @@ module Prawn
|
|
43
32
|
# Detected unknown option(s): [:tomato]
|
44
33
|
# Accepted options are: [:page_size, :page_layout, :left_margin, ...]
|
45
34
|
#
|
46
|
-
attr_accessor :debug
|
35
|
+
attr_accessor :debug # @private
|
47
36
|
|
48
|
-
def verify_options(accepted, actual)
|
37
|
+
def verify_options(accepted, actual) # @private
|
49
38
|
return unless debug || $DEBUG
|
50
39
|
unless (act=Set[*actual.keys]).subset?(acc=Set[*accepted])
|
51
40
|
raise Prawn::Errors::UnknownOption,
|
@@ -55,7 +44,7 @@ module Prawn
|
|
55
44
|
yield if block_given?
|
56
45
|
end
|
57
46
|
|
58
|
-
module Configurable
|
47
|
+
module Configurable # @private
|
59
48
|
def configuration(*args)
|
60
49
|
@config ||= Marshal.load(Marshal.dump(default_configuration))
|
61
50
|
if Hash === args[0]
|
@@ -75,7 +64,6 @@ end
|
|
75
64
|
|
76
65
|
require_relative "prawn/errors"
|
77
66
|
|
78
|
-
require_relative "pdf/core"
|
79
67
|
|
80
68
|
require_relative "prawn/utilities"
|
81
69
|
require_relative "prawn/text"
|
data/lib/prawn/document.rb
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
|
9
9
|
require "stringio"
|
10
|
+
|
10
11
|
require_relative "document/bounding_box"
|
11
12
|
require_relative "document/column_box"
|
12
13
|
require_relative "document/internals"
|
@@ -62,6 +63,8 @@ module Prawn
|
|
62
63
|
include Prawn::Stamp
|
63
64
|
include Prawn::SoftMask
|
64
65
|
|
66
|
+
# @group Extension API
|
67
|
+
|
65
68
|
# NOTE: We probably need to rethink the options validation system, but this
|
66
69
|
# constant temporarily allows for extensions to modify the list.
|
67
70
|
|
@@ -90,14 +93,28 @@ module Prawn
|
|
90
93
|
# party!
|
91
94
|
# end
|
92
95
|
#
|
96
|
+
#
|
93
97
|
def self.extensions
|
94
98
|
@extensions ||= []
|
95
99
|
end
|
96
100
|
|
97
|
-
|
101
|
+
# @private
|
102
|
+
def self.inherited(base)
|
98
103
|
extensions.each { |e| base.extensions << e }
|
99
104
|
end
|
100
105
|
|
106
|
+
# @group Stable Attributes
|
107
|
+
|
108
|
+
attr_accessor :margin_box
|
109
|
+
attr_reader :margins, :y
|
110
|
+
attr_accessor :page_number
|
111
|
+
|
112
|
+
# @group Extension Attributes
|
113
|
+
|
114
|
+
attr_accessor :text_formatter
|
115
|
+
|
116
|
+
# @group Stable API
|
117
|
+
|
101
118
|
# Creates and renders a PDF document.
|
102
119
|
#
|
103
120
|
# When using the implicit block form, Prawn will evaluate the block
|
@@ -215,27 +232,7 @@ module Prawn
|
|
215
232
|
end
|
216
233
|
end
|
217
234
|
|
218
|
-
|
219
|
-
attr_reader :margins, :y
|
220
|
-
attr_writer :font_size
|
221
|
-
attr_accessor :page_number
|
222
|
-
attr_accessor :text_formatter
|
223
|
-
|
224
|
-
def state
|
225
|
-
@internal_state
|
226
|
-
end
|
227
|
-
|
228
|
-
def page
|
229
|
-
state.page
|
230
|
-
end
|
231
|
-
|
232
|
-
def initialize_first_page(options)
|
233
|
-
if options[:skip_page_creation]
|
234
|
-
start_new_page(options.merge(:orphan => true))
|
235
|
-
else
|
236
|
-
start_new_page(options)
|
237
|
-
end
|
238
|
-
end
|
235
|
+
# @group Stable API
|
239
236
|
|
240
237
|
# Creates and advances to a new page in the document.
|
241
238
|
#
|
@@ -356,6 +353,9 @@ module Prawn
|
|
356
353
|
# Pass an open file descriptor to render to file.
|
357
354
|
#
|
358
355
|
def render(output = StringIO.new)
|
356
|
+
if output.instance_of?(StringIO)
|
357
|
+
output.set_encoding(::Encoding::ASCII_8BIT)
|
358
|
+
end
|
359
359
|
finalize_all_page_contents
|
360
360
|
|
361
361
|
render_header(output)
|
@@ -412,6 +412,7 @@ module Prawn
|
|
412
412
|
|
413
413
|
# Returns the innermost non-stretchy bounding box.
|
414
414
|
#
|
415
|
+
# @private
|
415
416
|
def reference_bounds
|
416
417
|
@bounding_box.reference_bounds
|
417
418
|
end
|
@@ -497,47 +498,6 @@ module Prawn
|
|
497
498
|
bounds.indent(left, right, &block)
|
498
499
|
end
|
499
500
|
|
500
|
-
|
501
|
-
def mask(*fields) # :nodoc:
|
502
|
-
# Stores the current state of the named attributes, executes the block, and
|
503
|
-
# then restores the original values after the block has executed.
|
504
|
-
# -- I will remove the nodoc if/when this feature is a little less hacky
|
505
|
-
stored = {}
|
506
|
-
fields.each { |f| stored[f] = send(f) }
|
507
|
-
yield
|
508
|
-
fields.each { |f| send("#{f}=", stored[f]) }
|
509
|
-
end
|
510
|
-
|
511
|
-
# Attempts to group the given block vertically within the current context.
|
512
|
-
# First attempts to render it in the current position on the current page.
|
513
|
-
# If that attempt overflows, it is tried anew after starting a new context
|
514
|
-
# (page or column). Returns a logically true value if the content fits in
|
515
|
-
# one page/column, false if a new page or column was needed.
|
516
|
-
#
|
517
|
-
# Raises CannotGroup if the provided content is too large to fit alone in
|
518
|
-
# the current page or column.
|
519
|
-
#
|
520
|
-
def group(second_attempt=false)
|
521
|
-
old_bounding_box = @bounding_box
|
522
|
-
@bounding_box = SimpleDelegator.new(@bounding_box)
|
523
|
-
|
524
|
-
def @bounding_box.move_past_bottom
|
525
|
-
raise RollbackTransaction
|
526
|
-
end
|
527
|
-
|
528
|
-
success = transaction { yield }
|
529
|
-
|
530
|
-
@bounding_box = old_bounding_box
|
531
|
-
|
532
|
-
unless success
|
533
|
-
raise Prawn::Errors::CannotGroup if second_attempt
|
534
|
-
old_bounding_box.move_past_bottom
|
535
|
-
group(second_attempt=true) { yield }
|
536
|
-
end
|
537
|
-
|
538
|
-
success
|
539
|
-
end
|
540
|
-
|
541
501
|
# Places a text box on specified pages for page numbering. This should be called
|
542
502
|
# towards the end of document creation, after all your content is already in
|
543
503
|
# place. In your template string, <page> refers to the current page, and
|
@@ -610,6 +570,46 @@ module Prawn
|
|
610
570
|
end
|
611
571
|
end
|
612
572
|
|
573
|
+
# Returns true if content streams will be compressed before rendering,
|
574
|
+
# false otherwise
|
575
|
+
#
|
576
|
+
def compression_enabled?
|
577
|
+
!!state.compress
|
578
|
+
end
|
579
|
+
|
580
|
+
# @group Experimental API
|
581
|
+
|
582
|
+
# Attempts to group the given block vertically within the current context.
|
583
|
+
# First attempts to render it in the current position on the current page.
|
584
|
+
# If that attempt overflows, it is tried anew after starting a new context
|
585
|
+
# (page or column). Returns a logically true value if the content fits in
|
586
|
+
# one page/column, false if a new page or column was needed.
|
587
|
+
#
|
588
|
+
# Raises CannotGroup if the provided content is too large to fit alone in
|
589
|
+
# the current page or column.
|
590
|
+
#
|
591
|
+
def group(second_attempt=false)
|
592
|
+
old_bounding_box = @bounding_box
|
593
|
+
@bounding_box = SimpleDelegator.new(@bounding_box)
|
594
|
+
|
595
|
+
# @private
|
596
|
+
def @bounding_box.move_past_bottom
|
597
|
+
raise RollbackTransaction
|
598
|
+
end
|
599
|
+
|
600
|
+
success = transaction { yield }
|
601
|
+
|
602
|
+
@bounding_box = old_bounding_box
|
603
|
+
|
604
|
+
unless success
|
605
|
+
raise Prawn::Errors::CannotGroup if second_attempt
|
606
|
+
old_bounding_box.move_past_bottom
|
607
|
+
group(second_attempt=true) { yield }
|
608
|
+
end
|
609
|
+
|
610
|
+
success
|
611
|
+
end
|
612
|
+
|
613
613
|
# Provides a way to execute a block of code repeatedly based on a
|
614
614
|
# page_filter.
|
615
615
|
#
|
@@ -635,16 +635,43 @@ module Prawn
|
|
635
635
|
end
|
636
636
|
end
|
637
637
|
|
638
|
+
# @private
|
639
|
+
|
640
|
+
def mask(*fields)
|
641
|
+
# Stores the current state of the named attributes, executes the block, and
|
642
|
+
# then restores the original values after the block has executed.
|
643
|
+
# -- I will remove the nodoc if/when this feature is a little less hacky
|
644
|
+
stored = {}
|
645
|
+
fields.each { |f| stored[f] = send(f) }
|
646
|
+
yield
|
647
|
+
fields.each { |f| send("#{f}=", stored[f]) }
|
648
|
+
end
|
638
649
|
|
639
|
-
#
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
650
|
+
# @group Extension API
|
651
|
+
|
652
|
+
def initialize_first_page(options)
|
653
|
+
if options[:skip_page_creation]
|
654
|
+
start_new_page(options.merge(:orphan => true))
|
655
|
+
else
|
656
|
+
start_new_page(options)
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
660
|
+
## Internals. Don't depend on them!
|
661
|
+
|
662
|
+
# @private
|
663
|
+
def state
|
664
|
+
@internal_state
|
665
|
+
end
|
666
|
+
|
667
|
+
# @private
|
668
|
+
def page
|
669
|
+
state.page
|
644
670
|
end
|
645
671
|
|
646
672
|
private
|
647
673
|
|
674
|
+
|
648
675
|
# setting override_settings to true ensures that a new graphic state does not end up using
|
649
676
|
# previous settings.
|
650
677
|
def use_graphic_settings(override_settings = false)
|
@@ -8,6 +8,7 @@
|
|
8
8
|
|
9
9
|
module Prawn
|
10
10
|
class Document
|
11
|
+
# @group Stable API
|
11
12
|
|
12
13
|
# :call-seq:
|
13
14
|
# bounding_box(point, options={}, &block)
|
@@ -219,7 +220,7 @@ module Prawn
|
|
219
220
|
#
|
220
221
|
class BoundingBox
|
221
222
|
|
222
|
-
def initialize(document, parent, point, options={})
|
223
|
+
def initialize(document, parent, point, options={}) # @private
|
223
224
|
unless options[:width]
|
224
225
|
raise ArgumentError, "BoundingBox needs the :width option to be set"
|
225
226
|
end
|
@@ -233,15 +234,22 @@ module Prawn
|
|
233
234
|
@stretched_height = nil
|
234
235
|
end
|
235
236
|
|
237
|
+
# @private
|
238
|
+
|
236
239
|
attr_reader :document, :parent
|
240
|
+
|
241
|
+
# @private
|
237
242
|
# The current indentation of the left side of the bounding box.
|
238
243
|
attr_reader :total_left_padding
|
244
|
+
|
245
|
+
# @private
|
239
246
|
# The current indentation of the right side of the bounding box.
|
240
247
|
attr_reader :total_right_padding
|
241
248
|
|
242
249
|
# The translated origin (x,y-height) which describes the location
|
243
250
|
# of the bottom left corner of the bounding box
|
244
251
|
#
|
252
|
+
# @private
|
245
253
|
def anchor
|
246
254
|
[@x, @y - height]
|
247
255
|
end
|
@@ -272,6 +280,7 @@ module Prawn
|
|
272
280
|
# text "indented on both sides"
|
273
281
|
# end
|
274
282
|
#
|
283
|
+
# @private
|
275
284
|
def indent(left_padding, right_padding = 0, &block)
|
276
285
|
add_left_padding(left_padding)
|
277
286
|
add_right_padding(right_padding)
|
@@ -282,6 +291,7 @@ module Prawn
|
|
282
291
|
end
|
283
292
|
|
284
293
|
# Increase the left padding of the bounding box.
|
294
|
+
# @private
|
285
295
|
def add_left_padding(left_padding)
|
286
296
|
@total_left_padding += left_padding
|
287
297
|
@x += left_padding
|
@@ -289,6 +299,7 @@ module Prawn
|
|
289
299
|
end
|
290
300
|
|
291
301
|
# Decrease the left padding of the bounding box.
|
302
|
+
# @private
|
292
303
|
def subtract_left_padding(left_padding)
|
293
304
|
@total_left_padding -= left_padding
|
294
305
|
@x -= left_padding
|
@@ -296,12 +307,14 @@ module Prawn
|
|
296
307
|
end
|
297
308
|
|
298
309
|
# Increase the right padding of the bounding box.
|
310
|
+
# @private
|
299
311
|
def add_right_padding(right_padding)
|
300
312
|
@total_right_padding += right_padding
|
301
313
|
@width -= right_padding
|
302
314
|
end
|
303
315
|
|
304
316
|
# Decrease the right padding of the bounding box.
|
317
|
+
# @private
|
305
318
|
def subtract_right_padding(right_padding)
|
306
319
|
@total_right_padding -= right_padding
|
307
320
|
@width += right_padding
|
@@ -452,15 +465,19 @@ module Prawn
|
|
452
465
|
end
|
453
466
|
|
454
467
|
# an alias for absolute_left
|
468
|
+
# @private
|
455
469
|
def left_side
|
456
470
|
absolute_left
|
457
471
|
end
|
458
472
|
|
459
473
|
# an alias for absolute_right
|
474
|
+
# @private
|
460
475
|
def right_side
|
461
476
|
absolute_right
|
462
477
|
end
|
463
478
|
|
479
|
+
# @group Extension API
|
480
|
+
|
464
481
|
# Moves to the top of the next page of the document, starting a new page
|
465
482
|
# if necessary.
|
466
483
|
#
|
@@ -472,9 +489,6 @@ module Prawn
|
|
472
489
|
end
|
473
490
|
end
|
474
491
|
|
475
|
-
|
476
|
-
alias_method :update_height, :height
|
477
|
-
|
478
492
|
# Returns +false+ when the box has a defined height, +true+ when the height
|
479
493
|
# is being calculated on the fly based on the current vertical position.
|
480
494
|
#
|
@@ -493,9 +507,12 @@ module Prawn
|
|
493
507
|
end
|
494
508
|
end
|
495
509
|
|
510
|
+
alias_method :update_height, :height
|
511
|
+
|
496
512
|
# Returns a deep copy of these bounds (including all parent bounds but
|
497
513
|
# not copying the reference to the Document).
|
498
514
|
#
|
515
|
+
# @private
|
499
516
|
def deep_copy
|
500
517
|
copy = dup
|
501
518
|
# Deep-copy the parent bounds
|
@@ -510,6 +527,7 @@ module Prawn
|
|
510
527
|
# context of the given +document+. Does *not* set the bounds of the
|
511
528
|
# document to the resulting BoundingBox, only returns it.
|
512
529
|
#
|
530
|
+
# @private
|
513
531
|
def self.restore_deep_copy(bounds, document)
|
514
532
|
bounds.instance_variable_set("@document", document)
|
515
533
|
bounds
|