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
data/lib/pdf/core.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
require_relative "core/pdf_object"
|
2
|
-
require_relative "core/annotations"
|
3
|
-
require_relative "core/byte_string"
|
4
|
-
require_relative "core/destinations"
|
5
|
-
require_relative "core/filters"
|
6
|
-
require_relative "core/stream"
|
7
|
-
require_relative "core/reference"
|
8
|
-
require_relative "core/literal_string"
|
9
|
-
require_relative "core/filter_list"
|
10
|
-
require_relative "core/page"
|
11
|
-
require_relative "core/object_store"
|
12
|
-
require_relative "core/document_state"
|
13
|
-
require_relative "core/name_tree"
|
14
|
-
require_relative "core/graphics_state"
|
15
|
-
require_relative "core/page_geometry"
|
16
|
-
require_relative "core/outline"
|
17
|
-
|
18
|
-
module PDF
|
19
|
-
module Core
|
20
|
-
module Errors
|
21
|
-
# This error is raised when PdfObject() fails
|
22
|
-
FailedObjectConversion = Class.new(StandardError)
|
23
|
-
|
24
|
-
# This error is raised when object store fails to load a template file
|
25
|
-
TemplateError = Class.new(StandardError)
|
26
|
-
|
27
|
-
# This error is raise when trying to restore a graphic state that
|
28
|
-
EmptyGraphicStateStack = Class.new(StandardError)
|
29
|
-
|
30
|
-
# This error is raised when Document#page_layout is set to anything
|
31
|
-
# other than :portrait or :landscape
|
32
|
-
InvalidPageLayout = Class.new(StandardError)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
data/lib/pdf/core/annotations.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# annotations.rb : Implements low-level annotation support for PDF
|
4
|
-
#
|
5
|
-
# Copyright November 2008, Jamis Buck. All Rights Reserved.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
#
|
9
|
-
module PDF
|
10
|
-
module Core
|
11
|
-
# Provides very low-level support for annotations.
|
12
|
-
#
|
13
|
-
module Annotations #:nodoc:
|
14
|
-
|
15
|
-
# Adds a new annotation (section 8.4 in PDF spec) to the current page.
|
16
|
-
# +options+ must be a Hash describing the annotation.
|
17
|
-
#
|
18
|
-
def annotate(options)
|
19
|
-
state.page.dictionary.data[:Annots] ||= []
|
20
|
-
options = sanitize_annotation_hash(options)
|
21
|
-
state.page.dictionary.data[:Annots] << ref!(options)
|
22
|
-
return options
|
23
|
-
end
|
24
|
-
|
25
|
-
# A convenience method for creating Text annotations. +rect+ must be an array
|
26
|
-
# of four numbers, describing the bounds of the annotation. +contents+ should
|
27
|
-
# be a string, to be shown when the annotation is activated.
|
28
|
-
#
|
29
|
-
def text_annotation(rect, contents, options={})
|
30
|
-
options = options.merge(:Subtype => :Text, :Rect => rect, :Contents => contents)
|
31
|
-
annotate(options)
|
32
|
-
end
|
33
|
-
|
34
|
-
# A convenience method for creating Link annotations. +rect+ must be an array
|
35
|
-
# of four numbers, describing the bounds of the annotation. The +options+ hash
|
36
|
-
# should include either :Dest (describing the target destination, usually as a
|
37
|
-
# string that has been recorded in the document's Dests tree), or :A (describing
|
38
|
-
# an action to perform on clicking the link), or :PA (for describing a URL to
|
39
|
-
# link to).
|
40
|
-
#
|
41
|
-
def link_annotation(rect, options={})
|
42
|
-
options = options.merge(:Subtype => :Link, :Rect => rect)
|
43
|
-
annotate(options)
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def sanitize_annotation_hash(options)
|
49
|
-
options = options.merge(:Type => :Annot)
|
50
|
-
|
51
|
-
if options[:Dest].is_a?(String)
|
52
|
-
options[:Dest] = PDF::Core::LiteralString.new(options[:Dest])
|
53
|
-
end
|
54
|
-
|
55
|
-
options
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
data/lib/pdf/core/byte_string.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# Implements destination support for PDF
|
4
|
-
#
|
5
|
-
# Copyright November 2008, Jamis Buck. All Rights Reserved.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
|
9
|
-
module PDF
|
10
|
-
module Core
|
11
|
-
module Destinations #:nodoc:
|
12
|
-
|
13
|
-
# The maximum number of children to fit into a single node in the Dests tree.
|
14
|
-
NAME_TREE_CHILDREN_LIMIT = 20 #:nodoc:
|
15
|
-
|
16
|
-
# The Dests name tree in the Name dictionary (see Prawn::Document::Internal#names).
|
17
|
-
# This name tree is used to store named destinations (PDF spec 8.2.1).
|
18
|
-
# (For more on name trees, see section 3.8.4 in the PDF spec.)
|
19
|
-
#
|
20
|
-
def dests
|
21
|
-
names.data[:Dests] ||= ref!(PDF::Core::NameTree::Node.new(self, NAME_TREE_CHILDREN_LIMIT))
|
22
|
-
end
|
23
|
-
|
24
|
-
# Adds a new destination to the dests name tree (see #dests). The
|
25
|
-
# +reference+ parameter will be converted into a PDF::Core::Reference if
|
26
|
-
# it is not already one.
|
27
|
-
#
|
28
|
-
def add_dest(name, reference)
|
29
|
-
reference = ref!(reference) unless reference.is_a?(PDF::Core::Reference)
|
30
|
-
dests.data.add(name, reference)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Return a Dest specification for a specific location (and optional zoom
|
34
|
-
# level).
|
35
|
-
#
|
36
|
-
def dest_xyz(left, top, zoom=nil, dest_page=page)
|
37
|
-
[dest_page.dictionary, :XYZ, left, top, zoom]
|
38
|
-
end
|
39
|
-
|
40
|
-
# Return a Dest specification that will fit the given page into the
|
41
|
-
# viewport.
|
42
|
-
#
|
43
|
-
def dest_fit(dest_page=page)
|
44
|
-
[dest_page.dictionary, :Fit]
|
45
|
-
end
|
46
|
-
|
47
|
-
# Return a Dest specification that will fit the given page horizontally
|
48
|
-
# into the viewport, aligned vertically at the given top coordinate.
|
49
|
-
#
|
50
|
-
def dest_fit_horizontally(top, dest_page=page)
|
51
|
-
[dest_page.dictionary, :FitH, top]
|
52
|
-
end
|
53
|
-
|
54
|
-
# Return a Dest specification that will fit the given page vertically
|
55
|
-
# into the viewport, aligned horizontally at the given left coordinate.
|
56
|
-
#
|
57
|
-
def dest_fit_vertically(left, dest_page=page)
|
58
|
-
[dest_page.dictionary, :FitV, left]
|
59
|
-
end
|
60
|
-
|
61
|
-
# Return a Dest specification that will fit the given rectangle into the
|
62
|
-
# viewport, for the given page.
|
63
|
-
#
|
64
|
-
def dest_fit_rect(left, bottom, right, top, dest_page=page)
|
65
|
-
[dest_page.dictionary, :FitR, left, bottom, right, top]
|
66
|
-
end
|
67
|
-
|
68
|
-
# Return a Dest specfication that will fit the given page's bounding box
|
69
|
-
# into the viewport.
|
70
|
-
#
|
71
|
-
def dest_fit_bounds(dest_page=page)
|
72
|
-
[dest_page.dictionary, :FitB]
|
73
|
-
end
|
74
|
-
|
75
|
-
# Same as #dest_fit_horizontally, but works on the page's bounding box
|
76
|
-
# instead of the entire page.
|
77
|
-
#
|
78
|
-
def dest_fit_bounds_horizontally(top, dest_page=page)
|
79
|
-
[dest_page.dictionary, :FitBH, top]
|
80
|
-
end
|
81
|
-
|
82
|
-
# Same as #dest_fit_vertically, but works on the page's bounding box
|
83
|
-
# instead of the entire page.
|
84
|
-
#
|
85
|
-
def dest_fit_bounds_vertically(left, dest_page=page)
|
86
|
-
[dest_page.dictionary, :FitBV, left]
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
@@ -1,79 +0,0 @@
|
|
1
|
-
module PDF
|
2
|
-
module Core
|
3
|
-
class DocumentState #:nodoc:
|
4
|
-
def initialize(options)
|
5
|
-
normalize_metadata(options)
|
6
|
-
|
7
|
-
if options[:template]
|
8
|
-
@store = PDF::Core::ObjectStore.new(:template => options[:template],
|
9
|
-
:print_scaling => options[:print_scaling])
|
10
|
-
@store.info.data.merge!(options[:info]) if options[:info]
|
11
|
-
else
|
12
|
-
@store = PDF::Core::ObjectStore.new(:info => options[:info], :print_scaling => options[:print_scaling])
|
13
|
-
end
|
14
|
-
|
15
|
-
@version = 1.3
|
16
|
-
@pages = []
|
17
|
-
@page = nil
|
18
|
-
@trailer = {}
|
19
|
-
@compress = options.fetch(:compress, false)
|
20
|
-
@encrypt = options.fetch(:encrypt, false)
|
21
|
-
@encryption_key = options[:encryption_key]
|
22
|
-
@optimize_objects = options.fetch(:optimize_objects, false)
|
23
|
-
@skip_encoding = options.fetch(:skip_encoding, false)
|
24
|
-
@before_render_callbacks = []
|
25
|
-
@on_page_create_callback = nil
|
26
|
-
end
|
27
|
-
|
28
|
-
attr_accessor :store, :version, :pages, :page, :trailer, :compress,
|
29
|
-
:encrypt, :encryption_key, :optimize_objects, :skip_encoding,
|
30
|
-
:before_render_callbacks, :on_page_create_callback
|
31
|
-
|
32
|
-
def populate_pages_from_store(document)
|
33
|
-
return 0 if @store.page_count <= 0 || @pages.size > 0
|
34
|
-
|
35
|
-
count = (1..@store.page_count)
|
36
|
-
@pages = count.map do |index|
|
37
|
-
orig_dict_id = @store.object_id_for_page(index)
|
38
|
-
PDF::Core::Page.new(document, :object_id => orig_dict_id)
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
def normalize_metadata(options)
|
44
|
-
options[:info] ||= {}
|
45
|
-
options[:info][:Creator] ||= "Prawn"
|
46
|
-
options[:info][:Producer] ||= "Prawn"
|
47
|
-
|
48
|
-
options[:info]
|
49
|
-
end
|
50
|
-
|
51
|
-
def insert_page(page, page_number)
|
52
|
-
pages.insert(page_number, page)
|
53
|
-
store.pages.data[:Kids].insert(page_number, page.dictionary)
|
54
|
-
store.pages.data[:Count] += 1
|
55
|
-
end
|
56
|
-
|
57
|
-
def on_page_create_action(doc)
|
58
|
-
on_page_create_callback[doc] if on_page_create_callback
|
59
|
-
end
|
60
|
-
|
61
|
-
def before_render_actions(doc)
|
62
|
-
before_render_callbacks.each{ |c| c.call(self) }
|
63
|
-
end
|
64
|
-
|
65
|
-
def page_count
|
66
|
-
pages.length
|
67
|
-
end
|
68
|
-
|
69
|
-
def render_body(output)
|
70
|
-
store.compact if optimize_objects
|
71
|
-
store.each do |ref|
|
72
|
-
ref.offset = output.size
|
73
|
-
output << (@encrypt ? ref.encrypted_object(@encryption_key) :
|
74
|
-
ref.object)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
data/lib/pdf/core/filter_list.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
module PDF
|
2
|
-
module Core
|
3
|
-
class FilterList
|
4
|
-
def initialize
|
5
|
-
@list = []
|
6
|
-
end
|
7
|
-
|
8
|
-
def <<(filter)
|
9
|
-
case filter
|
10
|
-
when Symbol
|
11
|
-
@list << [filter, nil]
|
12
|
-
when ::Hash
|
13
|
-
filter.each do |name, params|
|
14
|
-
@list << [name, params]
|
15
|
-
end
|
16
|
-
else
|
17
|
-
raise "Can not interpret input as filter: #{filter.inspect}"
|
18
|
-
end
|
19
|
-
|
20
|
-
self
|
21
|
-
end
|
22
|
-
|
23
|
-
def normalized
|
24
|
-
@list
|
25
|
-
end
|
26
|
-
alias_method :to_a, :normalized
|
27
|
-
|
28
|
-
def names
|
29
|
-
@list.map do |(name, _)|
|
30
|
-
name
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def decode_params
|
35
|
-
@list.map do |(_, params)|
|
36
|
-
params
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def inspect
|
41
|
-
@list.inspect
|
42
|
-
end
|
43
|
-
|
44
|
-
def each(&block)
|
45
|
-
@list.each do |filter|
|
46
|
-
block.call(filter)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
data/lib/pdf/core/filters.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# prawn/core/filters.rb : Implements stream filters
|
4
|
-
#
|
5
|
-
# Copyright February 2013, Alexander Mankuta. All Rights Reserved.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
|
9
|
-
require 'zlib'
|
10
|
-
|
11
|
-
module PDF
|
12
|
-
module Core
|
13
|
-
module Filters
|
14
|
-
module FlateDecode
|
15
|
-
def self.encode(stream, params = nil)
|
16
|
-
Zlib::Deflate.deflate(stream)
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.decode(stream, params = nil)
|
20
|
-
Zlib::Inflate.inflate(stream)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# Pass through stub
|
25
|
-
module DCTDecode
|
26
|
-
def self.encode(stream, params = nil)
|
27
|
-
stream
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.decode(stream, params = nil)
|
31
|
-
stream
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
#
|
3
|
-
# Implements graphics state saving and restoring
|
4
|
-
#
|
5
|
-
# Copyright January 2010, Michael Witrant. All Rights Reserved.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
module PDF
|
12
|
-
module Core
|
13
|
-
class GraphicStateStack
|
14
|
-
attr_accessor :stack
|
15
|
-
|
16
|
-
def initialize(previous_state = nil)
|
17
|
-
self.stack = [GraphicState.new(previous_state)]
|
18
|
-
end
|
19
|
-
|
20
|
-
def save_graphic_state(graphic_state = nil)
|
21
|
-
stack.push(GraphicState.new(graphic_state || current_state))
|
22
|
-
end
|
23
|
-
|
24
|
-
def restore_graphic_state
|
25
|
-
if stack.empty?
|
26
|
-
raise PDF::Core::Errors::EmptyGraphicStateStack,
|
27
|
-
"\n You have reached the end of the graphic state stack"
|
28
|
-
end
|
29
|
-
stack.pop
|
30
|
-
end
|
31
|
-
|
32
|
-
def current_state
|
33
|
-
stack.last
|
34
|
-
end
|
35
|
-
|
36
|
-
def present?
|
37
|
-
stack.size > 0
|
38
|
-
end
|
39
|
-
|
40
|
-
def empty?
|
41
|
-
stack.empty?
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
# NOTE: This class may be a good candidate for a copy-on-write hash.
|
47
|
-
class GraphicState
|
48
|
-
attr_accessor :color_space, :dash, :cap_style, :join_style, :line_width,
|
49
|
-
:fill_color, :stroke_color
|
50
|
-
|
51
|
-
def initialize(previous_state = nil)
|
52
|
-
if previous_state
|
53
|
-
initialize_copy(previous_state)
|
54
|
-
else
|
55
|
-
@color_space = {}
|
56
|
-
@fill_color = "000000"
|
57
|
-
@stroke_color = "000000"
|
58
|
-
@dash = { :dash => nil, :space => nil, :phase => 0 }
|
59
|
-
@cap_style = :butt
|
60
|
-
@join_style = :miter
|
61
|
-
@line_width = 1
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def dash_setting
|
66
|
-
if @dash[:dash].kind_of?(Array)
|
67
|
-
"[#{@dash[:dash].join(' ')}] #{@dash[:phase]} d"
|
68
|
-
else
|
69
|
-
"[#{@dash[:dash]} #{@dash[:space]}] #{@dash[:phase]} d"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
private
|
74
|
-
|
75
|
-
def initialize_copy(other)
|
76
|
-
# mutable state
|
77
|
-
@color_space = other.color_space.dup
|
78
|
-
@fill_color = other.fill_color.dup
|
79
|
-
@stroke_color = other.stroke_color.dup
|
80
|
-
@dash = other.dash.dup
|
81
|
-
|
82
|
-
# immutable state that doesn't need to be duped
|
83
|
-
@cap_style = other.cap_style
|
84
|
-
@join_style = other.join_style
|
85
|
-
@line_width = other.line_width
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|