pdf-core 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/Rakefile +9 -5
- data/lib/pdf/core.rb +20 -19
- data/lib/pdf/core/annotations.rb +16 -17
- data/lib/pdf/core/byte_string.rb +1 -1
- data/lib/pdf/core/destinations.rb +17 -14
- data/lib/pdf/core/document_state.rb +21 -16
- data/lib/pdf/core/filter_list.rb +4 -4
- data/lib/pdf/core/filters.rb +4 -4
- data/lib/pdf/core/graphics_state.rb +15 -19
- data/lib/pdf/core/name_tree.rb +44 -40
- data/lib/pdf/core/object_store.rb +13 -18
- data/lib/pdf/core/outline_item.rb +11 -6
- data/lib/pdf/core/outline_root.rb +1 -1
- data/lib/pdf/core/page.rb +93 -64
- data/lib/pdf/core/page_geometry.rb +52 -56
- data/lib/pdf/core/pdf_object.rb +41 -41
- data/lib/pdf/core/reference.rb +12 -17
- data/lib/pdf/core/renderer.rb +41 -32
- data/lib/pdf/core/stream.rb +6 -8
- data/lib/pdf/core/text.rb +83 -47
- data/lib/pdf/core/utils.rb +12 -0
- data/pdf-core.gemspec +33 -20
- metadata +79 -24
- metadata.gz.sig +0 -0
- data/spec/decimal_rounding_spec.rb +0 -12
- data/spec/document_state_spec.rb +0 -30
- data/spec/filters_spec.rb +0 -34
- data/spec/name_tree_spec.rb +0 -122
- data/spec/object_store_spec.rb +0 -49
- data/spec/pdf_object_spec.rb +0 -172
- data/spec/reference_spec.rb +0 -62
- data/spec/spec_helper.rb +0 -32
- data/spec/stream_spec.rb +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b927f3fa2dd24b6cdb4985d8b0d72f6b753cc3d1
|
4
|
+
data.tar.gz: 51de8ad704088ef8738768969444443379b57bcc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 589610d88baa8f03bbe3b4532cef5d780e0264d021933622d816c7b87b34ae8df06b5cd4e4276a2b159bcf6bbb1ae2ff0710d2cbe8cf37e44ce4c12ab7e04007
|
7
|
+
data.tar.gz: 525447dd1ed202a7880bbac27a7acc4cda730eae17b726c5ef2b3c46ec777dbdd8d794db8e36207d6a764b6e45caf007e628e76b139fc93d1f5c2ec8cb0f181d
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
data/Rakefile
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler'
|
2
2
|
Bundler.setup
|
3
3
|
|
4
4
|
require 'rake'
|
5
5
|
require 'rspec/core/rake_task'
|
6
|
-
task :default => [:spec]
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
task default: [:spec, :rubocop]
|
8
|
+
|
9
|
+
desc 'Run all rspec files'
|
10
|
+
RSpec::Core::RakeTask.new('spec') do |c|
|
11
|
+
c.rspec_opts = '-t ~unresolved'
|
11
12
|
end
|
13
|
+
|
14
|
+
require 'rubocop/rake_task'
|
15
|
+
RuboCop::RakeTask.new
|
data/lib/pdf/core.rb
CHANGED
@@ -1,26 +1,27 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
9
|
-
require_relative
|
10
|
-
require_relative
|
11
|
-
require_relative
|
12
|
-
require_relative
|
13
|
-
require_relative
|
14
|
-
require_relative
|
15
|
-
require_relative
|
16
|
-
require_relative
|
17
|
-
require_relative
|
18
|
-
require_relative
|
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_root'
|
17
|
+
require_relative 'core/outline_item'
|
18
|
+
require_relative 'core/renderer'
|
19
|
+
require_relative 'core/text'
|
19
20
|
|
20
21
|
module PDF
|
21
22
|
module Core
|
22
23
|
module Errors
|
23
|
-
# This error is raised when
|
24
|
+
# This error is raised when pdf_object() fails
|
24
25
|
FailedObjectConversion = Class.new(StandardError)
|
25
26
|
|
26
27
|
# This error is raise when trying to restore a graphic state that
|
data/lib/pdf/core/annotations.rb
CHANGED
@@ -11,7 +11,6 @@ module PDF
|
|
11
11
|
# Provides very low-level support for annotations.
|
12
12
|
#
|
13
13
|
module Annotations #:nodoc:
|
14
|
-
|
15
14
|
# Adds a new annotation (section 8.4 in PDF spec) to the current page.
|
16
15
|
# +options+ must be a Hash describing the annotation.
|
17
16
|
#
|
@@ -19,34 +18,35 @@ module PDF
|
|
19
18
|
state.page.dictionary.data[:Annots] ||= []
|
20
19
|
options = sanitize_annotation_hash(options)
|
21
20
|
state.page.dictionary.data[:Annots] << ref!(options)
|
22
|
-
|
21
|
+
options
|
23
22
|
end
|
24
23
|
|
25
|
-
# A convenience method for creating Text annotations. +rect+ must be an
|
26
|
-
# of four numbers, describing the bounds of the annotation.
|
27
|
-
# be a string, to be shown when the annotation is
|
24
|
+
# A convenience method for creating Text annotations. +rect+ must be an
|
25
|
+
# array of four numbers, describing the bounds of the annotation.
|
26
|
+
# +contents+ should be a string, to be shown when the annotation is
|
27
|
+
# activated.
|
28
28
|
#
|
29
|
-
def text_annotation(rect, contents, options={})
|
30
|
-
options = options.merge(:
|
29
|
+
def text_annotation(rect, contents, options = {})
|
30
|
+
options = options.merge(Subtype: :Text, Rect: rect, Contents: contents)
|
31
31
|
annotate(options)
|
32
32
|
end
|
33
33
|
|
34
|
-
# A convenience method for creating Link annotations. +rect+ must be an
|
35
|
-
# of four numbers, describing the bounds of the annotation. The
|
36
|
-
# should include either :Dest (describing the target
|
37
|
-
# string that has been recorded in the
|
38
|
-
#
|
39
|
-
# link to).
|
34
|
+
# A convenience method for creating Link annotations. +rect+ must be an
|
35
|
+
# array of four numbers, describing the bounds of the annotation. The
|
36
|
+
# +options+ hash should include either :Dest (describing the target
|
37
|
+
# destination, usually as a string that has been recorded in the
|
38
|
+
# document's Dests tree), or :A (describing an action to perform on
|
39
|
+
# clicking the link), or :PA (for describing a URL to link to).
|
40
40
|
#
|
41
|
-
def link_annotation(rect, options={})
|
42
|
-
options = options.merge(:
|
41
|
+
def link_annotation(rect, options = {})
|
42
|
+
options = options.merge(Subtype: :Link, Rect: rect)
|
43
43
|
annotate(options)
|
44
44
|
end
|
45
45
|
|
46
46
|
private
|
47
47
|
|
48
48
|
def sanitize_annotation_hash(options)
|
49
|
-
options = options.merge(:
|
49
|
+
options = options.merge(Type: :Annot)
|
50
50
|
|
51
51
|
if options[:Dest].is_a?(String)
|
52
52
|
options[:Dest] = PDF::Core::LiteralString.new(options[:Dest])
|
@@ -54,7 +54,6 @@ module PDF
|
|
54
54
|
|
55
55
|
options
|
56
56
|
end
|
57
|
-
|
58
57
|
end
|
59
58
|
end
|
60
59
|
end
|
data/lib/pdf/core/byte_string.rb
CHANGED
@@ -9,16 +9,19 @@
|
|
9
9
|
module PDF
|
10
10
|
module Core
|
11
11
|
module Destinations #:nodoc:
|
12
|
-
|
13
|
-
#
|
12
|
+
# The maximum number of children to fit into a single node in the Dests
|
13
|
+
# tree.
|
14
14
|
NAME_TREE_CHILDREN_LIMIT = 20 #:nodoc:
|
15
15
|
|
16
|
-
# The Dests name tree in the Name dictionary (see
|
17
|
-
# This name tree is used to store named
|
18
|
-
# (For more on name trees, see section
|
16
|
+
# The Dests name tree in the Name dictionary (see
|
17
|
+
# Prawn::Document::Internal#names). This name tree is used to store named
|
18
|
+
# destinations (PDF spec 8.2.1). (For more on name trees, see section
|
19
|
+
# 3.8.4 in the PDF spec.)
|
19
20
|
#
|
20
21
|
def dests
|
21
|
-
names.data[:Dests] ||= ref!(
|
22
|
+
names.data[:Dests] ||= ref!(
|
23
|
+
PDF::Core::NameTree::Node.new(self, NAME_TREE_CHILDREN_LIMIT)
|
24
|
+
)
|
22
25
|
end
|
23
26
|
|
24
27
|
# Adds a new destination to the dests name tree (see #dests). The
|
@@ -33,56 +36,56 @@ module PDF
|
|
33
36
|
# Return a Dest specification for a specific location (and optional zoom
|
34
37
|
# level).
|
35
38
|
#
|
36
|
-
def dest_xyz(left, top, zoom=nil, dest_page=page)
|
39
|
+
def dest_xyz(left, top, zoom = nil, dest_page = page)
|
37
40
|
[dest_page.dictionary, :XYZ, left, top, zoom]
|
38
41
|
end
|
39
42
|
|
40
43
|
# Return a Dest specification that will fit the given page into the
|
41
44
|
# viewport.
|
42
45
|
#
|
43
|
-
def dest_fit(dest_page=page)
|
46
|
+
def dest_fit(dest_page = page)
|
44
47
|
[dest_page.dictionary, :Fit]
|
45
48
|
end
|
46
49
|
|
47
50
|
# Return a Dest specification that will fit the given page horizontally
|
48
51
|
# into the viewport, aligned vertically at the given top coordinate.
|
49
52
|
#
|
50
|
-
def dest_fit_horizontally(top, dest_page=page)
|
53
|
+
def dest_fit_horizontally(top, dest_page = page)
|
51
54
|
[dest_page.dictionary, :FitH, top]
|
52
55
|
end
|
53
56
|
|
54
57
|
# Return a Dest specification that will fit the given page vertically
|
55
58
|
# into the viewport, aligned horizontally at the given left coordinate.
|
56
59
|
#
|
57
|
-
def dest_fit_vertically(left, dest_page=page)
|
60
|
+
def dest_fit_vertically(left, dest_page = page)
|
58
61
|
[dest_page.dictionary, :FitV, left]
|
59
62
|
end
|
60
63
|
|
61
64
|
# Return a Dest specification that will fit the given rectangle into the
|
62
65
|
# viewport, for the given page.
|
63
66
|
#
|
64
|
-
def dest_fit_rect(left, bottom, right, top, dest_page=page)
|
67
|
+
def dest_fit_rect(left, bottom, right, top, dest_page = page)
|
65
68
|
[dest_page.dictionary, :FitR, left, bottom, right, top]
|
66
69
|
end
|
67
70
|
|
68
71
|
# Return a Dest specfication that will fit the given page's bounding box
|
69
72
|
# into the viewport.
|
70
73
|
#
|
71
|
-
def dest_fit_bounds(dest_page=page)
|
74
|
+
def dest_fit_bounds(dest_page = page)
|
72
75
|
[dest_page.dictionary, :FitB]
|
73
76
|
end
|
74
77
|
|
75
78
|
# Same as #dest_fit_horizontally, but works on the page's bounding box
|
76
79
|
# instead of the entire page.
|
77
80
|
#
|
78
|
-
def dest_fit_bounds_horizontally(top, dest_page=page)
|
81
|
+
def dest_fit_bounds_horizontally(top, dest_page = page)
|
79
82
|
[dest_page.dictionary, :FitBH, top]
|
80
83
|
end
|
81
84
|
|
82
85
|
# Same as #dest_fit_vertically, but works on the page's bounding box
|
83
86
|
# instead of the entire page.
|
84
87
|
#
|
85
|
-
def dest_fit_bounds_vertically(left, dest_page=page)
|
88
|
+
def dest_fit_bounds_vertically(left, dest_page = page)
|
86
89
|
[dest_page.dictionary, :FitBV, left]
|
87
90
|
end
|
88
91
|
end
|
@@ -4,12 +4,15 @@ module PDF
|
|
4
4
|
def initialize(options)
|
5
5
|
normalize_metadata(options)
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
@store =
|
8
|
+
if options[:print_scaling]
|
9
|
+
PDF::Core::ObjectStore.new(
|
10
|
+
info: options[:info],
|
11
|
+
print_scaling: options[:print_scaling]
|
12
|
+
)
|
13
|
+
else
|
14
|
+
PDF::Core::ObjectStore.new(info: options[:info])
|
15
|
+
end
|
13
16
|
|
14
17
|
@version = 1.3
|
15
18
|
@pages = []
|
@@ -28,20 +31,19 @@ module PDF
|
|
28
31
|
:before_render_callbacks, :on_page_create_callback
|
29
32
|
|
30
33
|
def populate_pages_from_store(document)
|
31
|
-
return 0 if @store.page_count <= 0 ||
|
34
|
+
return 0 if @store.page_count <= 0 || !@pages.empty?
|
32
35
|
|
33
36
|
count = (1..@store.page_count)
|
34
37
|
@pages = count.map do |index|
|
35
38
|
orig_dict_id = @store.object_id_for_page(index)
|
36
|
-
PDF::Core::Page.new(document, :
|
39
|
+
PDF::Core::Page.new(document, object_id: orig_dict_id)
|
37
40
|
end
|
38
|
-
|
39
41
|
end
|
40
42
|
|
41
43
|
def normalize_metadata(options)
|
42
44
|
options[:info] ||= {}
|
43
|
-
options[:info][:Creator] ||=
|
44
|
-
options[:info][:Producer] ||=
|
45
|
+
options[:info][:Creator] ||= 'Prawn'
|
46
|
+
options[:info][:Producer] ||= 'Prawn'
|
45
47
|
|
46
48
|
options[:info]
|
47
49
|
end
|
@@ -56,8 +58,8 @@ module PDF
|
|
56
58
|
on_page_create_callback[doc] if on_page_create_callback
|
57
59
|
end
|
58
60
|
|
59
|
-
def before_render_actions(
|
60
|
-
before_render_callbacks.each{ |c| c.call(self) }
|
61
|
+
def before_render_actions(_doc)
|
62
|
+
before_render_callbacks.each { |c| c.call(self) }
|
61
63
|
end
|
62
64
|
|
63
65
|
def page_count
|
@@ -67,11 +69,14 @@ module PDF
|
|
67
69
|
def render_body(output)
|
68
70
|
store.each do |ref|
|
69
71
|
ref.offset = output.size
|
70
|
-
output <<
|
71
|
-
|
72
|
+
output <<
|
73
|
+
if @encrypt
|
74
|
+
ref.encrypted_object(@encryption_key)
|
75
|
+
else
|
76
|
+
ref.object
|
77
|
+
end
|
72
78
|
end
|
73
79
|
end
|
74
|
-
|
75
80
|
end
|
76
81
|
end
|
77
82
|
end
|
data/lib/pdf/core/filter_list.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module PDF
|
1
|
+
module PDF
|
2
2
|
module Core
|
3
3
|
class FilterList
|
4
4
|
def initialize
|
@@ -23,7 +23,7 @@ module PDF
|
|
23
23
|
def normalized
|
24
24
|
@list
|
25
25
|
end
|
26
|
-
|
26
|
+
alias to_a normalized
|
27
27
|
|
28
28
|
def names
|
29
29
|
@list.map do |(name, _)|
|
@@ -41,9 +41,9 @@ module PDF
|
|
41
41
|
@list.inspect
|
42
42
|
end
|
43
43
|
|
44
|
-
def each
|
44
|
+
def each
|
45
45
|
@list.each do |filter|
|
46
|
-
|
46
|
+
yield(filter)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
data/lib/pdf/core/filters.rb
CHANGED
@@ -12,22 +12,22 @@ module PDF
|
|
12
12
|
module Core
|
13
13
|
module Filters
|
14
14
|
module FlateDecode
|
15
|
-
def self.encode(stream,
|
15
|
+
def self.encode(stream, _params = nil)
|
16
16
|
Zlib::Deflate.deflate(stream)
|
17
17
|
end
|
18
18
|
|
19
|
-
def self.decode(stream,
|
19
|
+
def self.decode(stream, _params = nil)
|
20
20
|
Zlib::Inflate.inflate(stream)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
# Pass through stub
|
25
25
|
module DCTDecode
|
26
|
-
def self.encode(stream,
|
26
|
+
def self.encode(stream, _params = nil)
|
27
27
|
stream
|
28
28
|
end
|
29
29
|
|
30
|
-
def self.decode(stream,
|
30
|
+
def self.decode(stream, _params = nil)
|
31
31
|
stream
|
32
32
|
end
|
33
33
|
end
|
@@ -7,7 +7,6 @@
|
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details
|
8
8
|
#
|
9
9
|
|
10
|
-
|
11
10
|
module PDF
|
12
11
|
module Core
|
13
12
|
class GraphicStateStack
|
@@ -34,28 +33,27 @@ module PDF
|
|
34
33
|
end
|
35
34
|
|
36
35
|
def present?
|
37
|
-
stack.
|
36
|
+
!stack.empty?
|
38
37
|
end
|
39
38
|
|
40
39
|
def empty?
|
41
40
|
stack.empty?
|
42
41
|
end
|
43
|
-
|
44
42
|
end
|
45
43
|
|
46
44
|
# NOTE: This class may be a good candidate for a copy-on-write hash.
|
47
45
|
class GraphicState
|
48
|
-
attr_accessor :color_space, :dash, :cap_style, :join_style, :line_width,
|
49
|
-
|
46
|
+
attr_accessor :color_space, :dash, :cap_style, :join_style, :line_width,
|
47
|
+
:fill_color, :stroke_color
|
50
48
|
|
51
49
|
def initialize(previous_state = nil)
|
52
50
|
if previous_state
|
53
51
|
initialize_copy(previous_state)
|
54
52
|
else
|
55
53
|
@color_space = {}
|
56
|
-
@fill_color =
|
57
|
-
@stroke_color =
|
58
|
-
@dash = { :
|
54
|
+
@fill_color = '000000'
|
55
|
+
@stroke_color = '000000'
|
56
|
+
@dash = { dash: nil, space: nil, phase: 0 }
|
59
57
|
@cap_style = :butt
|
60
58
|
@join_style = :miter
|
61
59
|
@line_width = 1
|
@@ -63,17 +61,16 @@ module PDF
|
|
63
61
|
end
|
64
62
|
|
65
63
|
def dash_setting
|
66
|
-
return
|
64
|
+
return '[] 0 d' unless @dash[:dash]
|
67
65
|
|
68
|
-
if @dash[:dash].
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
"#{PDF::Core.real(@dash[:phase])} d"
|
66
|
+
array = if @dash[:dash].is_a?(Array)
|
67
|
+
@dash[:dash]
|
68
|
+
else
|
69
|
+
[@dash[:dash], @dash[:space]]
|
70
|
+
end
|
71
|
+
|
72
|
+
"[#{PDF::Core.real_params(array)}] "\
|
73
|
+
"#{PDF::Core.real(@dash[:phase])} d"
|
77
74
|
end
|
78
75
|
|
79
76
|
private
|
@@ -93,4 +90,3 @@ module PDF
|
|
93
90
|
end
|
94
91
|
end
|
95
92
|
end
|
96
|
-
|