pdfshaver 0.0.1.alpha
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|