origami 1.0.2

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.
Files changed (108) hide show
  1. data/COPYING.LESSER +165 -0
  2. data/README +77 -0
  3. data/VERSION +1 -0
  4. data/bin/config/pdfcop.conf.yml +237 -0
  5. data/bin/gui/about.rb +46 -0
  6. data/bin/gui/config.rb +132 -0
  7. data/bin/gui/file.rb +385 -0
  8. data/bin/gui/hexdump.rb +74 -0
  9. data/bin/gui/hexview.rb +91 -0
  10. data/bin/gui/imgview.rb +72 -0
  11. data/bin/gui/menu.rb +392 -0
  12. data/bin/gui/properties.rb +132 -0
  13. data/bin/gui/signing.rb +635 -0
  14. data/bin/gui/textview.rb +107 -0
  15. data/bin/gui/treeview.rb +409 -0
  16. data/bin/gui/walker.rb +282 -0
  17. data/bin/gui/xrefs.rb +79 -0
  18. data/bin/pdf2graph +121 -0
  19. data/bin/pdf2ruby +353 -0
  20. data/bin/pdfcocoon +104 -0
  21. data/bin/pdfcop +455 -0
  22. data/bin/pdfdecompress +104 -0
  23. data/bin/pdfdecrypt +95 -0
  24. data/bin/pdfencrypt +112 -0
  25. data/bin/pdfextract +221 -0
  26. data/bin/pdfmetadata +123 -0
  27. data/bin/pdfsh +13 -0
  28. data/bin/pdfwalker +7 -0
  29. data/bin/shell/.irbrc +104 -0
  30. data/bin/shell/console.rb +136 -0
  31. data/bin/shell/hexdump.rb +83 -0
  32. data/origami.rb +36 -0
  33. data/origami/3d.rb +239 -0
  34. data/origami/acroform.rb +321 -0
  35. data/origami/actions.rb +299 -0
  36. data/origami/adobe/fdf.rb +259 -0
  37. data/origami/adobe/ppklite.rb +489 -0
  38. data/origami/annotations.rb +775 -0
  39. data/origami/array.rb +187 -0
  40. data/origami/boolean.rb +101 -0
  41. data/origami/catalog.rb +486 -0
  42. data/origami/destinations.rb +213 -0
  43. data/origami/dictionary.rb +188 -0
  44. data/origami/docmdp.rb +96 -0
  45. data/origami/encryption.rb +1293 -0
  46. data/origami/export.rb +283 -0
  47. data/origami/file.rb +222 -0
  48. data/origami/filters.rb +250 -0
  49. data/origami/filters/ascii.rb +189 -0
  50. data/origami/filters/ccitt.rb +515 -0
  51. data/origami/filters/crypt.rb +47 -0
  52. data/origami/filters/dct.rb +61 -0
  53. data/origami/filters/flate.rb +112 -0
  54. data/origami/filters/jbig2.rb +63 -0
  55. data/origami/filters/jpx.rb +53 -0
  56. data/origami/filters/lzw.rb +195 -0
  57. data/origami/filters/predictors.rb +276 -0
  58. data/origami/filters/runlength.rb +117 -0
  59. data/origami/font.rb +209 -0
  60. data/origami/functions.rb +93 -0
  61. data/origami/graphics.rb +33 -0
  62. data/origami/graphics/colors.rb +191 -0
  63. data/origami/graphics/instruction.rb +126 -0
  64. data/origami/graphics/path.rb +154 -0
  65. data/origami/graphics/patterns.rb +180 -0
  66. data/origami/graphics/state.rb +164 -0
  67. data/origami/graphics/text.rb +224 -0
  68. data/origami/graphics/xobject.rb +493 -0
  69. data/origami/header.rb +90 -0
  70. data/origami/linearization.rb +318 -0
  71. data/origami/metadata.rb +114 -0
  72. data/origami/name.rb +170 -0
  73. data/origami/null.rb +75 -0
  74. data/origami/numeric.rb +188 -0
  75. data/origami/obfuscation.rb +233 -0
  76. data/origami/object.rb +527 -0
  77. data/origami/outline.rb +59 -0
  78. data/origami/page.rb +559 -0
  79. data/origami/parser.rb +268 -0
  80. data/origami/parsers/fdf.rb +45 -0
  81. data/origami/parsers/pdf.rb +27 -0
  82. data/origami/parsers/pdf/linear.rb +113 -0
  83. data/origami/parsers/ppklite.rb +86 -0
  84. data/origami/pdf.rb +1144 -0
  85. data/origami/reference.rb +113 -0
  86. data/origami/signature.rb +474 -0
  87. data/origami/stream.rb +575 -0
  88. data/origami/string.rb +416 -0
  89. data/origami/trailer.rb +173 -0
  90. data/origami/webcapture.rb +87 -0
  91. data/origami/xfa.rb +3027 -0
  92. data/origami/xreftable.rb +447 -0
  93. data/templates/patterns.rb +66 -0
  94. data/templates/widgets.rb +173 -0
  95. data/templates/xdp.rb +92 -0
  96. data/tests/dataset/test.dummycrt +28 -0
  97. data/tests/dataset/test.dummykey +27 -0
  98. data/tests/tc_actions.rb +32 -0
  99. data/tests/tc_annotations.rb +85 -0
  100. data/tests/tc_pages.rb +37 -0
  101. data/tests/tc_pdfattach.rb +24 -0
  102. data/tests/tc_pdfencrypt.rb +110 -0
  103. data/tests/tc_pdfnew.rb +32 -0
  104. data/tests/tc_pdfparse.rb +98 -0
  105. data/tests/tc_pdfsig.rb +37 -0
  106. data/tests/tc_streams.rb +129 -0
  107. data/tests/ts_pdf.rb +45 -0
  108. metadata +193 -0
@@ -0,0 +1,93 @@
1
+ =begin
2
+
3
+ = File
4
+ functions.rb
5
+
6
+ = Info
7
+ This file is part of Origami, PDF manipulation framework for Ruby
8
+ Copyright (C) 2010 Guillaume Delugr� <guillaume@security-labs.org>
9
+ All right reserved.
10
+
11
+ Origami is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU Lesser General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ Origami is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU Lesser General Public License for more details.
20
+
21
+ You should have received a copy of the GNU Lesser General Public License
22
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
23
+
24
+ =end
25
+
26
+
27
+ module Origami
28
+
29
+ module Function
30
+
31
+ module Type
32
+ SAMPLED = 0
33
+ EXPONENTIAL = 2
34
+ STITCHING = 3
35
+ POSTSCRIPT = 4
36
+ end
37
+
38
+ def self.included(receiver)
39
+ receiver.field :FunctionType, :Type => Integer, :Required => true
40
+ receiver.field :Domain, :Type => Array, :Required => true
41
+ receiver.field :Range, :Type => Array
42
+ end
43
+
44
+ class Sampled < Stream
45
+
46
+ include Function
47
+
48
+ field :FunctionType, :Type => Integer, :Default => Type::SAMPLED, :Version => "1.3", :Required => true
49
+ field :Range, :Type => Array, :Required => true
50
+ field :Size, :Type => Array, :Required => true
51
+ field :BitsPerSample, :Type => Integer, :Required => true
52
+ field :Order, :Type => Integer, :Default => 1
53
+ field :Encode, :Type => Array
54
+ field :Decode, :Type => Array
55
+
56
+ end
57
+
58
+ class Exponential < Dictionary
59
+
60
+ include StandardObject
61
+ include Function
62
+
63
+ field :FunctionType, :Type => Integer, :Default => Type::EXPONENTIAL, :Version => "1.3", :Required => true
64
+ field :C0, :Type => Array, :Default => [ 0.0 ]
65
+ field :C1, :Type => Array, :Default => [ 1.0 ]
66
+ field :N, :Type => Number, :Required => true
67
+
68
+ end
69
+
70
+ class Stitching < Dictionary
71
+
72
+ include StandardObject
73
+ include Function
74
+
75
+ field :FunctionType, :Type => Integer, :Default => Type::STITCHING, :Version => "1.3", :Required => true
76
+ field :Functions, :Type => Array, :Required => true
77
+ field :Bounds, :Type => Array, :Required => true
78
+ field :Encode, :Type => Array, :Required => true
79
+
80
+ end
81
+
82
+ class PostScript < Stream
83
+
84
+ include Function
85
+
86
+ field :FunctionType, :Type => Integer, :Default => Type::POSTSCRIPT, :Version => "1.3", :Required => true
87
+ field :Range, :Type => Array, :Required => true
88
+
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,33 @@
1
+ =begin
2
+
3
+ = File
4
+ graphics.rb
5
+
6
+ = Info
7
+ This file is part of Origami, PDF manipulation framework for Ruby
8
+ Copyright (C) 2010 Guillaume Delugr� <guillaume@security-labs.org>
9
+ All right reserved.
10
+
11
+ Origami is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU Lesser General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ Origami is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU Lesser General Public License for more details.
20
+
21
+ You should have received a copy of the GNU Lesser General Public License
22
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
23
+
24
+ =end
25
+
26
+ require 'origami/graphics/instruction'
27
+ require 'origami/graphics/colors'
28
+ require 'origami/graphics/path'
29
+ require 'origami/graphics/xobject'
30
+ require 'origami/graphics/patterns'
31
+ require 'origami/graphics/text'
32
+ require 'origami/graphics/state'
33
+
@@ -0,0 +1,191 @@
1
+ =begin
2
+
3
+ = File
4
+ graphics/colors.rb
5
+
6
+ = Info
7
+ This file is part of Origami, PDF manipulation framework for Ruby
8
+ Copyright (C) 2010 Guillaume Delugré <guillaume@security-labs.org>
9
+ All right reserved.
10
+
11
+ Origami is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU Lesser General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ Origami is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU Lesser General Public License for more details.
20
+
21
+ You should have received a copy of the GNU Lesser General Public License
22
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
23
+
24
+ =end
25
+
26
+ begin
27
+ require 'color'
28
+ rescue LoadError
29
+ end
30
+
31
+ module Origami
32
+
33
+ module Graphics
34
+
35
+ module RenderingIntent
36
+ ABSOLUTE_COLORIMETRIC = :AbsoluteColorimetric
37
+ RELATIVE_COLORIMETRIC = :RelativeColorimetric
38
+ SATURATION = :Saturation
39
+ PERCEPTUAL = :Perceptual
40
+ end
41
+
42
+ module BlendMode
43
+ NORMAL = :Normal
44
+ COMPATIBLE = :Compatible
45
+ MULTIPLY = :Multiply
46
+ SCREEN = :Screen
47
+ OVERLAY = :Overlay
48
+ DARKEN = :Darken
49
+ LIGHTEN = :Lighten
50
+ COLORDODGE = :ColorDodge
51
+ COLORBURN = :ColorBurn
52
+ HARDLIGHT = :HardLight
53
+ SOFTLIGHt = :SoftLight
54
+ DIFFERENCE = :Difference
55
+ EXCLUSION = :Exclusion
56
+ end
57
+
58
+ class InvalidColorError < Exception; end
59
+ module Color
60
+
61
+ module Space
62
+ DEVICE_GRAY = :DeviceGray
63
+ DEVICE_RGB = :DeviceRGB
64
+ DEVICE_CMYK = :DeviceCMYK
65
+ end
66
+
67
+ class GrayScale
68
+ attr_accessor :g
69
+
70
+ def initialize(g)
71
+ @g = g
72
+ end
73
+ end
74
+
75
+ class RGB
76
+ attr_accessor :r,:g,:b
77
+
78
+ def initialize(r,g,b)
79
+ @r,@g,@b = r,g,b
80
+ end
81
+ end
82
+
83
+ class CMYK
84
+ attr_accessor :c,:m,:y,:k
85
+
86
+ def initialize(c,m,y,k)
87
+ @c,@m,@y,@k = c,m,y,k
88
+ end
89
+ end
90
+
91
+ def Color.to_a(color)
92
+ return color if color.is_a?(::Array)
93
+
94
+ if (color.respond_to? :r and color.respond_to? :g and color.respond_to? :b)
95
+ r = (color.respond_to?(:r) ? color.r : color[0]).to_f / 255
96
+ g = (color.respond_to?(:g) ? color.g : color[1]).to_f / 255
97
+ b = (color.respond_to?(:b) ? color.b : color[2]).to_f / 255
98
+ return [r, g, b]
99
+
100
+ elsif (color.respond_to? :c and color.respond_to? :m and color.respond_to? :y and color.respond_to? :k)
101
+ c = (color.respond_to?(:c) ? color.c : color[0]).to_f
102
+ m = (color.respond_to?(:m) ? color.m : color[1]).to_f
103
+ y = (color.respond_to?(:y) ? color.y : color[2]).to_f
104
+ k = (color.respond_to?(:k) ? color.k : color[3]).to_f
105
+ return [c,m,y,k]
106
+
107
+ elsif color.respond_to?:g or (0.0..1.0) === color
108
+ g = color.respond_to?(:g) ? color.g : color
109
+ return [ g ]
110
+
111
+ else
112
+ raise TypeError, "Invalid color : #{color}"
113
+ end
114
+ end
115
+ end
116
+
117
+ end
118
+
119
+ class PDF::Instruction
120
+
121
+ insn 'CS', Name do |gs, cs| gs.stroking_colorspace = cs end
122
+ insn 'cs', Name do |gs, cs| gs.nonstroking_colorspace = cs end
123
+ insn 'SC', '*' do |gs, *c| gs.stroking_color = c end
124
+ insn 'sc', '*' do |gs, *c| gs.nonstroking_color = c end
125
+
126
+ insn 'G', Real do |gs, c|
127
+ unless (0..1).include? c
128
+ raise Graphics::InvalidColorError,
129
+ "Not a valid color for DeviceGray: #{c}"
130
+ end
131
+
132
+ gs.stroking_colorspace = Graphics::Color::Space::DEVICE_GRAY
133
+ gs.stroking_color = [ c ]
134
+ end
135
+
136
+ insn 'g', Real do |gs, c|
137
+ unless (0..1).include? c
138
+ raise Graphics::InvalidColorError,
139
+ "Not a valid color for DeviceGray: #{c}"
140
+ end
141
+
142
+ gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_GRAY
143
+ gs.nonstroking_color = [ c ]
144
+ end
145
+
146
+ insn 'RG', Real, Real, Real do |gs, r,g,b|
147
+ c = [ r, g, b ]
148
+ unless c.all? {|b| (0..1).include? b}
149
+ raise Graphics::InvalidColorError,
150
+ "Not a valid color for DeviceRGB: #{c.inspect}"
151
+ end
152
+
153
+ gs.stroking_colorspace = Graphics::Color::Space::DEVICE_RGB
154
+ gs.stroking_color = c
155
+ end
156
+
157
+ insn 'rg', Real, Real, Real do |gs, r,g,b|
158
+ c = [ r, g, b ]
159
+ unless c.all? {|b| (0..1).include? b}
160
+ raise Graphics::InvalidColorError,
161
+ "Not a valid color for DeviceRGB: #{c.inspect}"
162
+ end
163
+
164
+ gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_RGB
165
+ gs.nonstroking_color = c
166
+ end
167
+
168
+ insn 'K', Real, Real, Real, Real do |gs, c,m,y,k|
169
+ c = [ c, m, y, k ]
170
+ unless c.all? {|b| (0..1).include? b}
171
+ raise Graphics::InvalidColorError,
172
+ "Not a valid color for DeviceCMYK: #{c.inspect}"
173
+ end
174
+
175
+ gs.stroking_colorspace = Graphics::Color::Space::DEVICE_CMYK
176
+ gs.stroking_color = c
177
+ end
178
+
179
+ insn 'k', Real, Real, Real, Real do |gs, c,m,y,k|
180
+ c = [ c, m, y, k ]
181
+ unless c.all? {|b| (0..1).include? b}
182
+ raise Graphics::InvalidColorError,
183
+ "Not a valid color for DeviceCMYK: #{c.inspect}"
184
+ end
185
+
186
+ gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_CMYK
187
+ gs.nonstroking_color = c
188
+ end
189
+ end
190
+
191
+ end # module Origami
@@ -0,0 +1,126 @@
1
+ =begin
2
+
3
+ = File
4
+ graphics/instruction.rb
5
+
6
+ = Info
7
+ This file is part of Origami, PDF manipulation framework for Ruby
8
+ Copyright (C) 2010 Guillaume Delugré <guillaume@security-labs.org>
9
+ All right reserved.
10
+
11
+ Origami is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU Lesser General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ Origami is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU Lesser General Public License for more details.
20
+
21
+ You should have received a copy of the GNU Lesser General Public License
22
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
23
+
24
+ =end
25
+
26
+ module Origami
27
+
28
+ class InvalidPDFInstructionError < Exception ; end
29
+ class PDF::Instruction
30
+ attr_reader :operator
31
+ attr_accessor :operands
32
+
33
+ @@regexp = Regexp.new('([^ \\t\\r\\n\\0\\[\\]<>()%\\/]+)')
34
+ @insns = Hash.new(:operands => [], :proc => lambda{}, :callback => lambda{})
35
+
36
+ def initialize(operator, *operands)
37
+ @operator = operator
38
+ @operands = operands.map!{|arg| arg.is_a?(Origami::Object) ? arg.value : arg}
39
+
40
+ if self.class.has_op?(operator)
41
+ opdef = self.class.get_operands(operator)
42
+
43
+ if not opdef.include?('*') and opdef.size != operands.size
44
+ raise InvalidPDFInstructionError,
45
+ "Numbers of operands mismatch for #{operator}: #{operands.inspect}"
46
+ end
47
+ end
48
+ end
49
+
50
+ def update_state(gs)
51
+ self.class.get_proc(@operator)[gs, *operands] if self.class.has_proc?(@operator)
52
+ self
53
+ end
54
+
55
+ def render
56
+ end
57
+
58
+ def exec(gs)
59
+ update_state(gs)
60
+ self.class.get_callback(@operator)[gs] if self.class.has_callback?(@operator)
61
+
62
+ self
63
+ end
64
+
65
+ def to_s
66
+ "#{operands.map!{|op| op.to_o.to_s}.join(' ')}#{' ' unless operands.empty?}#{operator}\n"
67
+ end
68
+
69
+ class << self
70
+ def insn(operator, *operands, &p)
71
+ @insns[operator] = {}
72
+ @insns[operator][:operands] = operands
73
+ @insns[operator][:proc] = p if block_given?
74
+ end
75
+
76
+ def has_op?(operator)
77
+ @insns.has_key? operator
78
+ end
79
+
80
+ def has_proc?(operator)
81
+ self.has_op?(operator) and @insns[operator].has_key?(:proc)
82
+ end
83
+
84
+ def has_callback?(operator)
85
+ self.has_op?(operator) and @insns[operator].has_key?(:callback)
86
+ end
87
+
88
+ def set_callback(operator, &b)
89
+ raise RuntimeError, "Operator `#{operator}' does not exist" unless @insns.has_key?(operator)
90
+ @insns[operator][:callback] = b
91
+ end
92
+
93
+ def get_proc(operator)
94
+ @insns[operator][:proc]
95
+ end
96
+
97
+ def get_operands(operator)
98
+ @insns[operator][:operands]
99
+ end
100
+
101
+ def parse(stream)
102
+ operands = []
103
+ while type = Object.typeof(stream, true)
104
+ operands.unshift type.parse(stream)
105
+ end
106
+
107
+ if not stream.eos?
108
+ if stream.scan(@@regexp).nil?
109
+ raise InvalidPDFInstructionError,
110
+ "Operator: #{(stream.peek(10) + '...').inspect}"
111
+ end
112
+
113
+ operator = stream[1]
114
+ PDF::Instruction.new(operator, *operands)
115
+ else
116
+ if not operands.empty?
117
+ raise InvalidPDFInstructionError,
118
+ "No operator given for operands: #{operands.join}"
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ end
125
+ end
126
+
@@ -0,0 +1,154 @@
1
+ =begin
2
+
3
+ = File
4
+ graphics/path.rb
5
+
6
+ = Info
7
+ This file is part of Origami, PDF manipulation framework for Ruby
8
+ Copyright (C) 2010 Guillaume Delugré <guillaume@security-labs.org>
9
+ All right reserved.
10
+
11
+ Origami is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU Lesser General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ Origami is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU Lesser General Public License for more details.
20
+
21
+ You should have received a copy of the GNU Lesser General Public License
22
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
23
+
24
+ =end
25
+
26
+ module Origami
27
+
28
+ module Graphics
29
+
30
+ module LineCapStyle
31
+ BUTT_CAP = 0
32
+ ROUND_CAP = 1
33
+ PROJECTING_SQUARE_CAP = 2
34
+ end
35
+
36
+ module LineJoinStyle
37
+ MITER_JOIN = 0
38
+ ROUND_JOIN = 1
39
+ BEVEL_JOIN = 2
40
+ end
41
+
42
+ class DashPattern
43
+ attr_accessor :array, :phase
44
+
45
+ def initialize(array, phase = 0)
46
+ @array = array
47
+ @phase = phase
48
+ end
49
+
50
+ def eql?(dash) #:nodoc
51
+ dash.array == @array and dash.phase == @phase
52
+ end
53
+
54
+ def hash #:nodoc:
55
+ [ @array, @phase ].hash
56
+ end
57
+ end
58
+
59
+ class InvalidPathError < Exception; end
60
+ class Path
61
+
62
+ module Segment
63
+ attr_accessor :from, :to
64
+
65
+ def initialize(from, to)
66
+ @from, @to = from, to
67
+ end
68
+ end
69
+
70
+ class Line
71
+ include Segment
72
+ end
73
+
74
+ attr_accessor :current_point
75
+ attr_reader :segments
76
+
77
+ def initialize
78
+ @segments = []
79
+ @current_point = nil
80
+ @closed = false
81
+ end
82
+
83
+ def is_closed?
84
+ @closed
85
+ end
86
+
87
+ def close!
88
+ from = @current_point
89
+ to = @segments.first.from
90
+
91
+ @segments << Line.new(from, to)
92
+ @segments.freeze
93
+ @closed = true
94
+ end
95
+
96
+ def add_segment(seg)
97
+ raise GraphicsStateError, "Cannot modify closed subpath" if is_closed?
98
+
99
+ @segments << seg
100
+ @current_point = seg.to
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
107
+ class PDF::Instruction
108
+ insn 'm', Real, Real do |gs, x,y|
109
+ gs.current_path << (subpath = Graphics::Path.new)
110
+ subpath.current_point = [x,y]
111
+ end
112
+
113
+ insn 'l', Real, Real do |gs, x,y|
114
+ if gs.current_path.empty?
115
+ raise InvalidPathError, "No current point is defined"
116
+ end
117
+
118
+ subpath = gs.current_path.last
119
+
120
+ from = subpath.current_point
121
+ to = [x,y]
122
+ subpath.add_segment(Graphics::Path::Line.new(from, to))
123
+ end
124
+
125
+ insn 'h' do |gs|
126
+ unless gs.current_path.empty?
127
+ subpath = gs.current_path.last
128
+ subpath.close! unless subpath.is_closed?
129
+ end
130
+ end
131
+
132
+ insn 're', Real, Real, Real, Real do |gs, x,y,width,height|
133
+ tx = x + width
134
+ ty = y + height
135
+ gs.current_path << (subpath = Graphics::Path.new)
136
+ subpath.segments << Graphics::Path::Line.new([x,y], [tx,y])
137
+ subpath.segments << Graphics::Path::Line.new([tx,y], [tx, ty])
138
+ subpath.segments << Graphics::Path::Line.new([tx, ty], [x, ty])
139
+ subpath.close!
140
+ end
141
+
142
+ insn 'S'
143
+ insn 's' do |gs| gs.current_path.last.close! end
144
+ insn 'f'
145
+ insn 'F'
146
+ insn 'f*'
147
+ insn 'B'
148
+ insn 'B*'
149
+ insn 'b' do |gs| gs.current_path.last.close! end
150
+ insn 'b*' do |gs| gs.current_path.last.close! end
151
+ insn 'n'
152
+ end
153
+
154
+ end