jpeg2pdf 0.12

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.
@@ -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