jpeg2pdf 0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,61 @@
1
+ require 'rpdf/crossreftable'
2
+ require 'rpdf/documentcatalog'
3
+ require 'rpdf/pagetree'
4
+ require 'rpdf/trailer'
5
+ require 'rpdf/version'
6
+
7
+ module RPDF
8
+ class Document
9
+ attr_reader :pdf_version, :pagetree, :root, :xrefs
10
+
11
+ def initialize(pdf, pdf_version = VERSION_DEFAULT)
12
+ @pdf = pdf
13
+ @pdf_version = pdf_version
14
+ @objects = Array.new
15
+ @pagetree = PageTree.new(self)
16
+ @root = DocumentCatalog.new(self)
17
+ @xrefs = CrossRefTable.new
18
+
19
+ # File Header [PDFRef15 p68]
20
+ bytes = @pdf_version.to_pdf
21
+ bytes << "����\n" # Ensure file transfer applications detect the file as binary. [PDFRef15 p69]
22
+ @numwritten = bytes.size
23
+ @pdf.write(bytes)
24
+
25
+ end
26
+
27
+ def new_id(object)
28
+ @objects << object
29
+ @objects.size
30
+ end
31
+
32
+ def size
33
+ @objects.size
34
+ end
35
+
36
+ def write(object)
37
+ objectbytes = object.to_pdf
38
+ @xrefs.addUsedEntry(@numwritten, object.object_number) # position of the next object in the PDF file
39
+ @pdf.write(objectbytes)
40
+ @numwritten = @numwritten + objectbytes.size
41
+ end
42
+
43
+ def close_pdf
44
+ trailer = Trailer.new(self)
45
+ bytes = String.new
46
+
47
+ # File Body [PDFRef15 p69]
48
+ @objects.each { |object|
49
+ object.invalidate unless object.invalidated?
50
+ }
51
+
52
+ trailer.startxref = @numwritten
53
+
54
+ # Cross-Reference Table [PDFRef15 p69]
55
+ @pdf.write(@xrefs.to_pdf)
56
+
57
+ # File Trailer [PDFRef15 p72]
58
+ @pdf.write(trailer.to_pdf)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,18 @@
1
+ require 'rpdf/pdfdictionary'
2
+ require 'rpdf/document'
3
+
4
+ module RPDF
5
+
6
+ # Document Catalog Object
7
+ # [PDFRef15 p113]
8
+ class DocumentCatalog < PDFDictionary
9
+
10
+ def initialize(document)
11
+ super({ :Type => :Catalog,
12
+ :Pages => document.pagetree },
13
+ document)
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,23 @@
1
+ require 'rpdf/pdfdictionary'
2
+
3
+ module RPDF
4
+
5
+ # Image Dictionary Object
6
+ # [PDFRef15 p303]
7
+ class ImageDictionary < PDFDictionary
8
+
9
+ # colorspace: :DeviceGrey, :DeviceRGB or :DeviceCMYK
10
+ # bpc: 8, 12 or 16
11
+ def initialize(width, height, colorspace, bpc, document=nil)
12
+ super({ :Type => :XObject,
13
+ :Subtype => :Image,
14
+ :Width => width,
15
+ :Height => height,
16
+ :ColorSpace => colorspace,
17
+ :BitsPerComponent => bpc },
18
+ document)
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,21 @@
1
+ require 'rpdf/pdfdictionary'
2
+
3
+ module RPDF
4
+
5
+ # Page Object
6
+ # [PDFRef15 p118]
7
+ class Page < PDFDictionary
8
+
9
+ def initialize(document, parent)
10
+ super({ :Type => :Page,
11
+ :Parent => parent,
12
+ :Resources => {},
13
+ :MediaBox => Rectangle.new(0, 0, 612, 792) },
14
+ document)
15
+
16
+ parent.add_page(self)
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,24 @@
1
+ require 'rpdf/pdfdictionary'
2
+
3
+ module RPDF
4
+
5
+ # Page Tree Object
6
+ # [PDFRef15 p116]
7
+ class PageTree < PDFDictionary
8
+
9
+ def initialize(document, parent=nil)
10
+ super({ :Type => :Pages,
11
+ :Parent => parent,
12
+ :Kids => [],
13
+ :Count => 0 },
14
+ document)
15
+ end
16
+
17
+ def add_page(page)
18
+ self[:Kids] << page
19
+ self[:Count] = self[:Count].value + 1
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,35 @@
1
+ require 'rpdf/pdfobject'
2
+ require 'rpdf/util'
3
+
4
+ module RPDF
5
+
6
+ # Array Object
7
+ # [PDFRef15 p34]
8
+ class PDFArray < PDFObject
9
+ attr_reader :array
10
+
11
+ def initialize(array, document=nil)
12
+ raise Exception.new("PDFArray is not an array") unless array.kind_of?(Array)
13
+ @array = Array.new
14
+ array.each { |object|
15
+ @array << RPDF.topdfobject(object, document)
16
+ }
17
+ super(document)
18
+ end
19
+
20
+ def <<(element)
21
+ @array << RPDF.topdfobject(element)
22
+ end
23
+
24
+ def to_s
25
+ bytes = "[ "
26
+ @array.each { |element|
27
+ bytes << element.to_ref # to_ref -> reference to indirect object
28
+ bytes << " "
29
+ }
30
+ bytes << "]"
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,28 @@
1
+ require 'rpdf/pdfobject'
2
+
3
+ module RPDF
4
+
5
+ # Boolean Object: true or false
6
+ # [PDFRef15 p28]
7
+ class PDFBoolean < PDFObject
8
+ include Comparable
9
+
10
+ attr_reader :value
11
+
12
+ def initialize(value, document=nil)
13
+ raise Exception.new("PDFBoolean not true nor false") unless (value.kind_of?(TrueClass) or value.kind_of?(FalseClass))
14
+ @value = value
15
+ super(document)
16
+ end
17
+
18
+ def <=>(other)
19
+ @value <=> other.value
20
+ end
21
+
22
+ def to_s
23
+ @value.to_s
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,51 @@
1
+ require 'rpdf/pdfobject'
2
+ require 'rpdf/util'
3
+
4
+ module RPDF
5
+
6
+ # Dictionary Object
7
+ # [PDFRef15 p35]
8
+ class PDFDictionary < PDFObject
9
+ attr_reader :dict
10
+
11
+ def initialize(dict, document=nil)
12
+ raise Exception.new("PDFDictionary is not a hash") unless dict.kind_of?(Hash)
13
+ @dict = Hash.new
14
+ dict.each { |key, value|
15
+ pdfkey = RPDF.topdfobject(key)
16
+ pdfvalue = RPDF.topdfobject(value)
17
+ raise Exception.new("PDFDictionary key must be a name") unless pdfkey.kind_of?(PDFName)
18
+ @dict[pdfkey] = pdfvalue
19
+ }
20
+ super(document)
21
+ end
22
+
23
+ def [](key)
24
+ pdfkey = RPDF.topdfobject(key)
25
+ raise Exception.new("PDFDictionary key must be a name") unless pdfkey.kind_of?(PDFName)
26
+ @dict[pdfkey]
27
+ end
28
+
29
+ def []=(key, value)
30
+ pdfkey = RPDF.topdfobject(key)
31
+ pdfvalue = RPDF.topdfobject(value)
32
+ raise Exception.new("PDFDictionary key must be a name") unless pdfkey.kind_of?(PDFName)
33
+ @dict[pdfkey] = pdfvalue
34
+ end
35
+
36
+ # Update dictionary with other dictionary
37
+ def update(other)
38
+ @dict.update(other.dict)
39
+ end
40
+
41
+ def to_s
42
+ bytes = "<< "
43
+ @dict.each { |key, value|
44
+ bytes << "#{key.to_s} #{value.to_ref}\n" # to_ref -> reference to indirect object
45
+ }
46
+ bytes << ">>\n"
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,17 @@
1
+ require 'rpdf/pdfnumeric'
2
+
3
+ module RPDF
4
+
5
+ # Integer Object
6
+ # This is not a real PDF Object, as PDF knows only Numerics.
7
+ # [PDFRef15 p28]
8
+ class PDFInteger < PDFNumeric
9
+
10
+ def initialize(value, document=nil)
11
+ raise Exception.new("PDFInteger is not an integer") unless value.kind_of?(Integer)
12
+ super
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,35 @@
1
+ require 'rpdf/pdfobject'
2
+ require 'rpdf/util'
3
+
4
+ module RPDF
5
+
6
+ # Name Object
7
+ # [PDFRef15 p32]
8
+ class PDFName < PDFObject
9
+ attr_reader :value
10
+
11
+ def initialize(value, document=nil)
12
+ raise Exception.new("PDFName is not a string") unless value.kind_of?(String)
13
+ raise Exception.new("PDFName has whitespace") if RPDF.includes_whitespace?(value)
14
+ raise Exception.new("PDFName has delimiter") if RPDF.includes_delimiter?(value)
15
+ @value = value
16
+ super(document)
17
+ end
18
+
19
+ def hash
20
+ @value.hash
21
+ end
22
+
23
+ # To make PDFName possible to use as a key in a PDFDictionary
24
+ def eql?(other)
25
+ @value.eql?(other.value)
26
+ end
27
+
28
+ # TODO: 2-digit hexadecimal code for characters outside the range 33 (!) to 126 (~) [PDFRef15 p33]
29
+ def to_s
30
+ "/#{@value}"
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,19 @@
1
+ require 'rpdf/pdfobject'
2
+
3
+ module RPDF
4
+
5
+ # Null Object: null
6
+ # [PDFRef15 p39]
7
+ class PDFNull < PDFObject
8
+
9
+ def initialize
10
+ super
11
+ end
12
+
13
+ def to_s
14
+ "null"
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,28 @@
1
+ require 'rpdf/pdfobject'
2
+
3
+ module RPDF
4
+
5
+ # Numeric Object
6
+ # [PDFRef15 p28]
7
+ class PDFNumeric < PDFObject
8
+ include Comparable
9
+
10
+ attr_reader :value
11
+
12
+ def initialize(value, document=nil)
13
+ raise Exception.new("PDFNumeric is not a number") unless value.kind_of?(Numeric)
14
+ @value = value
15
+ super(document)
16
+ end
17
+
18
+ def <=>(other)
19
+ @value <=> other.value
20
+ end
21
+
22
+ def to_s
23
+ @value.to_s
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,60 @@
1
+ module RPDF
2
+
3
+ # An object which is a part of a PDF document. [PDFRef15 p27]
4
+ class PDFObject
5
+
6
+ attr_reader :object_number, :generation_number
7
+
8
+ # Make an indirect object if a document is passed, otherwise a direct object.
9
+ def initialize(document=nil)
10
+ if document
11
+ @object_number = document.new_id(self)
12
+ @document = document
13
+ else
14
+ @object_number = 0 # The object number of an indirect object should be positive
15
+ end
16
+ @generation_number = 0
17
+ @invalidated = false
18
+ end
19
+
20
+ def indirect?
21
+ @object_number > 0
22
+ end
23
+
24
+ # Subclasses has to call this in their invalidate method if they override it
25
+ def invalidate
26
+ @document.write(self)
27
+ @invalidated = true
28
+ end
29
+
30
+ # true if the object has already been written to the PDF stream
31
+ def invalidated?
32
+ @invalidated
33
+ end
34
+
35
+ # Return a representation suitable to write to a PDF file
36
+ # [PDFRef15 p39]
37
+ def to_pdf
38
+ if indirect?
39
+ bytes = "#{@object_number} #{@generation_number} obj\n"
40
+ bytes << to_s << "\n"
41
+ bytes << "endobj\n\n"
42
+ else
43
+ to_s
44
+ end
45
+ end
46
+
47
+ # Return an indirect reference to this object if it's indirect,
48
+ # return the bytestream otherwise.
49
+ # [PDFRef15 p39]
50
+ def to_ref
51
+ if indirect?
52
+ "#{@object_number} #{@generation_number} R"
53
+ else
54
+ to_s
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,32 @@
1
+ require 'rpdf/pdfdictionary'
2
+ require 'rpdf/pdfobject'
3
+
4
+ module RPDF
5
+
6
+ # Stream Object
7
+ # TODO: stream dictionary
8
+ # [PDFRef15 p36]
9
+ class PDFStream < PDFObject
10
+ attr_reader :data, :dict
11
+
12
+ def initialize(data, document=nil)
13
+ @data = data
14
+ @dict = PDFDictionary.new({ :Length => data.size })
15
+ super(document)
16
+ end
17
+
18
+ def invalidate
19
+ super
20
+ @data = nil
21
+ end
22
+
23
+ def to_s
24
+ bytes = @dict.to_pdf
25
+ bytes << "stream\n"
26
+ bytes << data
27
+ bytes << "\nendstream"
28
+ end
29
+
30
+ end
31
+
32
+ end