pdfshaver 0.0.1.alpha
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 +7 -0
- data/Gemfile +3 -0
- data/Rakefile +10 -0
- data/Readme.md +14 -0
- data/ext/pdfium_ruby/document.cpp +131 -0
- data/ext/pdfium_ruby/document.h +53 -0
- data/ext/pdfium_ruby/extconf.rb +68 -0
- data/ext/pdfium_ruby/page.cpp +190 -0
- data/ext/pdfium_ruby/page.h +36 -0
- data/ext/pdfium_ruby/pdfium_ruby.cpp +17 -0
- data/ext/pdfium_ruby/pdfium_ruby.h +20 -0
- data/lib/pdfshaver.rb +13 -0
- data/lib/pdfshaver/document.rb +21 -0
- data/lib/pdfshaver/page.rb +117 -0
- data/lib/pdfshaver/page_set.rb +83 -0
- data/lib/pdfshaver/version.rb +3 -0
- data/pdfshaver.gemspec +29 -0
- data/test/document_spec.rb +36 -0
- data/test/fixtures/completely_encrypted.pdf +0 -0
- data/test/fixtures/encrypted.pdf +0 -0
- data/test/fixtures/letter-to-canadians-from-jack-layton.pdf +0 -0
- data/test/fixtures/uncharter.pdf +0 -0
- data/test/gm_compatability_spec.rb +92 -0
- data/test/page_set_spec.rb +62 -0
- data/test/page_spec.rb +133 -0
- data/test/spec_helper.rb +13 -0
- metadata +140 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'spec_helper'))
|
2
|
+
|
3
|
+
describe PDFShaver::PageSet do
|
4
|
+
|
5
|
+
before do
|
6
|
+
path = File.join(FIXTURES, 'uncharter.pdf')
|
7
|
+
@document = PDFShaver::Document.new(path)
|
8
|
+
@first_half_range = Range.new(1, @document.length/2)
|
9
|
+
@last_half_range = Range.new(@document.length/2, @document.length)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be an enumerable collection of pages" do
|
13
|
+
pages = PDFShaver::PageSet.new(@document)
|
14
|
+
pages.must_be_instance_of PDFShaver::PageSet
|
15
|
+
pages.must_respond_to(:each)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should iterate all pages by default" do
|
19
|
+
counter = 0
|
20
|
+
PDFShaver::PageSet.new(@document).each{ |page| counter += 1 }
|
21
|
+
counter.must_equal @document.length
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should iterate through a specified list of pages" do
|
25
|
+
counter = 0
|
26
|
+
PDFShaver::PageSet.new(@document, @first_half_range).each{ |page| counter += 1 }
|
27
|
+
counter.must_equal @document.length/2
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should provide a number of ways to express page lists" do
|
31
|
+
{ 1 => 1,
|
32
|
+
[1,2,3,5,8] => 5,
|
33
|
+
5..10 => 6,
|
34
|
+
[1, 5..10] => 7
|
35
|
+
}.each do |list, count|
|
36
|
+
#puts list.inspect
|
37
|
+
PDFShaver::PageSet.new(@document, list).size.must_equal count
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should reject any page value that's out of bounds" do
|
42
|
+
[5000, -1, 5..-5, 10..8].each do|input|
|
43
|
+
Proc.new{ PDFShaver::PageSet.new(@document, input) }.must_raise ArgumentError
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should provide an accessor, #first and #last to specify the set" do
|
48
|
+
pages = PDFShaver::PageSet.new(@document, @last_half_range)
|
49
|
+
pages.first.must_equal PDFShaver::Page.new(@document, @last_half_range.first)
|
50
|
+
pages.last.must_equal PDFShaver::Page.new(@document, @last_half_range.last)
|
51
|
+
pages[1].must_equal PDFShaver::Page.new(@document, @last_half_range.first+1)
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "Document PageSet Interface" do
|
55
|
+
it { @document.pages.must_be_instance_of PDFShaver::PageSet }
|
56
|
+
|
57
|
+
it "should have accessors to specific pages" do
|
58
|
+
@document.pages[0].must_equal PDFShaver::Page.new(@document, 1)
|
59
|
+
@document.pages[@document.length-1].must_equal PDFShaver::Page.new(@document, @document.length)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/test/page_spec.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'spec_helper'))
|
2
|
+
|
3
|
+
describe PDFShaver::Page do
|
4
|
+
before do
|
5
|
+
path = File.join(FIXTURES, 'uncharter.pdf')
|
6
|
+
@document = PDFShaver::Document.new(path)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should be instantiated" do
|
10
|
+
PDFShaver::Page.new(@document, 1).must_be_instance_of PDFShaver::Page
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should throw an error if initialized without a document" do
|
14
|
+
Proc.new{ PDFShaver::Page.new("lol", 1) }.must_raise ArgumentError
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should only instantiate pages with a valid page number" do
|
18
|
+
Proc.new{ PDFShaver::Page.new(@document) }.must_raise ArgumentError
|
19
|
+
Proc.new{ PDFShaver::Page.new(@document, -12) }.must_raise ArgumentError
|
20
|
+
Proc.new{ PDFShaver::Page.new(@document, 0) }.must_raise ArgumentError
|
21
|
+
Proc.new{ PDFShaver::Page.new(@document, @document.length+1) }.must_raise ArgumentError
|
22
|
+
|
23
|
+
PDFShaver::Page.new(@document, 1).must_be_instance_of PDFShaver::Page
|
24
|
+
PDFShaver::Page.new(@document, @document.length).must_be_instance_of PDFShaver::Page
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "instance methods" do
|
28
|
+
before do
|
29
|
+
@page = PDFShaver::Page.new(@document, 1)
|
30
|
+
@output_path = File.join OUTPUT, 'image_render_test.gif'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have the right width, height and aspect ratio" do
|
34
|
+
@page.width.must_be_kind_of Integer
|
35
|
+
@page.height.must_be_kind_of Integer
|
36
|
+
@page.aspect.must_be_kind_of Float
|
37
|
+
@page.document.must_be_same_as @document
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should have a comparator and know which order pages go in" do
|
41
|
+
p1 = PDFShaver::Page.new(@document, 1)
|
42
|
+
p2 = PDFShaver::Page.new(@document, 2)
|
43
|
+
p3 = PDFShaver::Page.new(@document, 3)
|
44
|
+
|
45
|
+
(p2 <=> p1).must_equal 1
|
46
|
+
(p2 <=> p2).must_equal 0
|
47
|
+
(p2 <=> p3).must_equal -1
|
48
|
+
|
49
|
+
Proc.new{ p2 <=> :lol }.must_raise ArgumentError
|
50
|
+
end
|
51
|
+
|
52
|
+
it { @page.must_equal @page }
|
53
|
+
it { @page.must_equal PDFShaver::Page.new(@document,@page.number) }
|
54
|
+
|
55
|
+
it "shouldn't be equal to a page with the same number from another document" do
|
56
|
+
other_document = PDFShaver::Document.new(File.join(FIXTURES, 'letter-to-canadians-from-jack-layton.pdf'))
|
57
|
+
(@page.document).wont_equal other_document
|
58
|
+
@page.wont_equal PDFShaver::Page.new(other_document, @page.number)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should render an image and write it out to disk" do
|
62
|
+
@page.render(@output_path).must_equal true
|
63
|
+
File.exists?(@output_path).must_equal true
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should throw an error when saving to an unrecognized file type" do
|
67
|
+
fail_path = File.join(OUTPUT, "this_will_never_be.a_valid_filetype")
|
68
|
+
Proc.new{ @page.render(fail_path) }.must_raise ArgumentError
|
69
|
+
File.exists?(fail_path).must_equal false
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should raise an error if output path is missing" do
|
73
|
+
Proc.new{ @page.render }.must_raise ArgumentError
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should use default page size if dimensions aren't specified" do
|
77
|
+
@page.render @output_path
|
78
|
+
FastImage.size(@output_path).zip([@page.width, @page.height]).each do |actual, expected|
|
79
|
+
actual.must_equal expected
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should scale image when height is specified" do
|
84
|
+
target_height = 1000
|
85
|
+
@page.render @output_path, height:target_height, width:nil
|
86
|
+
width, height = FastImage.size @output_path
|
87
|
+
height.must_equal target_height
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should scale image when width is specified" do
|
91
|
+
target_width = 1000
|
92
|
+
@page.render @output_path, height:nil, width:target_width
|
93
|
+
width, height = FastImage.size @output_path
|
94
|
+
width.must_equal target_width
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should scale image when height and width are specified" do
|
98
|
+
target_height = target_width = 1000
|
99
|
+
@page.render @output_path, height:target_height, width:target_width
|
100
|
+
width, height = FastImage.size @output_path
|
101
|
+
width.must_equal target_width
|
102
|
+
height.must_equal target_height
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should preserve aspect ratio when scaling" do
|
106
|
+
@page.render @output_path, height:1000, width:nil
|
107
|
+
width, height = FastImage.size @output_path
|
108
|
+
(width.to_f / height).must_be_within_delta @page.aspect, 0.001
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "GC" do
|
113
|
+
it "won't segfault if when a document is GCed" do
|
114
|
+
doc = PDFShaver::Document.new(File.join(FIXTURES,'uncharter.pdf'))
|
115
|
+
doc = nil
|
116
|
+
GC.start
|
117
|
+
end
|
118
|
+
|
119
|
+
it "won't segfault if when an invalid document is GCed" do
|
120
|
+
Proc.new{ PDFShaver::Document.new("suede shoes") }.must_raise ArgumentError
|
121
|
+
GC.start
|
122
|
+
end
|
123
|
+
|
124
|
+
it "won't segfault if document falls out of scope before pages" do
|
125
|
+
doc = PDFShaver::Document.new(File.join(FIXTURES,'uncharter.pdf'))
|
126
|
+
p1 = PDFShaver::Page.new(doc, 1)
|
127
|
+
doc = nil
|
128
|
+
GC.start
|
129
|
+
p1 = nil
|
130
|
+
GC.start
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/test/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require 'fastimage'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
HERE = File.expand_path File.dirname(__FILE__)
|
6
|
+
FIXTURES = File.join(HERE, 'fixtures')
|
7
|
+
OUTPUT = File.join(HERE, 'output')
|
8
|
+
FileUtils.mkdir_p OUTPUT
|
9
|
+
|
10
|
+
MiniTest::Unit.after_tests { FileUtils.rm_r(OUTPUT) if File.exists?(OUTPUT) and not ENV["DEBUG"] }
|
11
|
+
|
12
|
+
require File.join(HERE, '..', 'lib', 'pdfshaver')
|
13
|
+
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pdfshaver
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.alpha
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ted Han
|
8
|
+
- Nathan Stitt
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-02-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.5'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.5'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake-compiler
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: minitest
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: fastimage
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
description:
|
85
|
+
email: opensource@documentcloud.org
|
86
|
+
executables: []
|
87
|
+
extensions:
|
88
|
+
- ext/pdfium_ruby/extconf.rb
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- Gemfile
|
92
|
+
- Rakefile
|
93
|
+
- Readme.md
|
94
|
+
- ext/pdfium_ruby/document.cpp
|
95
|
+
- ext/pdfium_ruby/document.h
|
96
|
+
- ext/pdfium_ruby/extconf.rb
|
97
|
+
- ext/pdfium_ruby/page.cpp
|
98
|
+
- ext/pdfium_ruby/page.h
|
99
|
+
- ext/pdfium_ruby/pdfium_ruby.cpp
|
100
|
+
- ext/pdfium_ruby/pdfium_ruby.h
|
101
|
+
- lib/pdfshaver.rb
|
102
|
+
- lib/pdfshaver/document.rb
|
103
|
+
- lib/pdfshaver/page.rb
|
104
|
+
- lib/pdfshaver/page_set.rb
|
105
|
+
- lib/pdfshaver/version.rb
|
106
|
+
- pdfshaver.gemspec
|
107
|
+
- test/document_spec.rb
|
108
|
+
- test/fixtures/completely_encrypted.pdf
|
109
|
+
- test/fixtures/encrypted.pdf
|
110
|
+
- test/fixtures/letter-to-canadians-from-jack-layton.pdf
|
111
|
+
- test/fixtures/uncharter.pdf
|
112
|
+
- test/gm_compatability_spec.rb
|
113
|
+
- test/page_set_spec.rb
|
114
|
+
- test/page_spec.rb
|
115
|
+
- test/spec_helper.rb
|
116
|
+
homepage:
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">"
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 1.3.1
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.4.5
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: Shave pages off of PDFs as images
|
140
|
+
test_files: []
|