origami 1.2.7 → 2.0.0

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 (162) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -0
  3. data/README.md +112 -0
  4. data/bin/config/pdfcop.conf.yml +232 -233
  5. data/bin/gui/about.rb +27 -37
  6. data/bin/gui/config.rb +108 -117
  7. data/bin/gui/file.rb +416 -365
  8. data/bin/gui/gtkhex.rb +1138 -1153
  9. data/bin/gui/hexview.rb +55 -57
  10. data/bin/gui/imgview.rb +48 -51
  11. data/bin/gui/menu.rb +388 -386
  12. data/bin/gui/properties.rb +114 -130
  13. data/bin/gui/signing.rb +571 -617
  14. data/bin/gui/textview.rb +77 -95
  15. data/bin/gui/treeview.rb +382 -387
  16. data/bin/gui/walker.rb +227 -232
  17. data/bin/gui/xrefs.rb +56 -60
  18. data/bin/pdf2pdfa +53 -57
  19. data/bin/pdf2ruby +212 -228
  20. data/bin/pdfcop +338 -348
  21. data/bin/pdfdecompress +58 -65
  22. data/bin/pdfdecrypt +56 -60
  23. data/bin/pdfencrypt +75 -80
  24. data/bin/pdfexplode +185 -182
  25. data/bin/pdfextract +201 -218
  26. data/bin/pdfmetadata +83 -82
  27. data/bin/pdfsh +4 -5
  28. data/bin/pdfwalker +1 -2
  29. data/bin/shell/.irbrc +45 -82
  30. data/bin/shell/console.rb +105 -130
  31. data/bin/shell/hexdump.rb +40 -64
  32. data/examples/README.md +34 -0
  33. data/examples/attachments/attachment.rb +38 -0
  34. data/examples/attachments/nested_document.rb +51 -0
  35. data/examples/encryption/encryption.rb +28 -0
  36. data/{samples/actions/triggerevents/trigger.rb → examples/events/events.rb} +13 -16
  37. data/examples/flash/flash.rb +37 -0
  38. data/{samples → examples}/flash/helloworld.swf +0 -0
  39. data/examples/forms/javascript.rb +54 -0
  40. data/examples/forms/xfa.rb +115 -0
  41. data/examples/javascript/hello_world.rb +22 -0
  42. data/examples/javascript/js_emulation.rb +54 -0
  43. data/examples/loop/goto.rb +32 -0
  44. data/examples/loop/named.rb +33 -0
  45. data/examples/signature/signature.rb +65 -0
  46. data/examples/uri/javascript.rb +56 -0
  47. data/examples/uri/open-uri.rb +21 -0
  48. data/examples/uri/submitform.rb +47 -0
  49. data/lib/origami.rb +29 -42
  50. data/lib/origami/3d.rb +350 -225
  51. data/lib/origami/acroform.rb +262 -288
  52. data/lib/origami/actions.rb +268 -288
  53. data/lib/origami/annotations.rb +697 -722
  54. data/lib/origami/array.rb +258 -184
  55. data/lib/origami/boolean.rb +74 -84
  56. data/lib/origami/catalog.rb +397 -434
  57. data/lib/origami/collections.rb +144 -0
  58. data/lib/origami/destinations.rb +233 -194
  59. data/lib/origami/dictionary.rb +253 -232
  60. data/lib/origami/encryption.rb +1274 -1243
  61. data/lib/origami/export.rb +232 -268
  62. data/lib/origami/extensions/fdf.rb +307 -220
  63. data/lib/origami/extensions/ppklite.rb +368 -435
  64. data/lib/origami/filespec.rb +197 -0
  65. data/lib/origami/filters.rb +301 -295
  66. data/lib/origami/filters/ascii.rb +177 -180
  67. data/lib/origami/filters/ccitt.rb +528 -535
  68. data/lib/origami/filters/crypt.rb +26 -35
  69. data/lib/origami/filters/dct.rb +46 -52
  70. data/lib/origami/filters/flate.rb +95 -94
  71. data/lib/origami/filters/jbig2.rb +49 -55
  72. data/lib/origami/filters/jpx.rb +38 -44
  73. data/lib/origami/filters/lzw.rb +189 -183
  74. data/lib/origami/filters/predictors.rb +221 -235
  75. data/lib/origami/filters/runlength.rb +103 -104
  76. data/lib/origami/font.rb +173 -186
  77. data/lib/origami/functions.rb +67 -81
  78. data/lib/origami/graphics.rb +25 -21
  79. data/lib/origami/graphics/colors.rb +178 -187
  80. data/lib/origami/graphics/instruction.rb +79 -85
  81. data/lib/origami/graphics/path.rb +142 -148
  82. data/lib/origami/graphics/patterns.rb +160 -167
  83. data/lib/origami/graphics/render.rb +43 -50
  84. data/lib/origami/graphics/state.rb +138 -153
  85. data/lib/origami/graphics/text.rb +188 -205
  86. data/lib/origami/graphics/xobject.rb +819 -815
  87. data/lib/origami/header.rb +63 -78
  88. data/lib/origami/javascript.rb +596 -597
  89. data/lib/origami/linearization.rb +285 -290
  90. data/lib/origami/metadata.rb +139 -148
  91. data/lib/origami/name.rb +112 -148
  92. data/lib/origami/null.rb +53 -62
  93. data/lib/origami/numeric.rb +162 -175
  94. data/lib/origami/obfuscation.rb +186 -174
  95. data/lib/origami/object.rb +593 -573
  96. data/lib/origami/outline.rb +42 -47
  97. data/lib/origami/outputintents.rb +73 -82
  98. data/lib/origami/page.rb +703 -592
  99. data/lib/origami/parser.rb +238 -290
  100. data/lib/origami/parsers/fdf.rb +41 -33
  101. data/lib/origami/parsers/pdf.rb +75 -95
  102. data/lib/origami/parsers/pdf/lazy.rb +137 -0
  103. data/lib/origami/parsers/pdf/linear.rb +64 -66
  104. data/lib/origami/parsers/ppklite.rb +34 -70
  105. data/lib/origami/pdf.rb +1030 -1005
  106. data/lib/origami/reference.rb +102 -102
  107. data/lib/origami/signature.rb +591 -609
  108. data/lib/origami/stream.rb +668 -551
  109. data/lib/origami/string.rb +397 -373
  110. data/lib/origami/template/patterns.rb +56 -0
  111. data/lib/origami/template/widgets.rb +151 -0
  112. data/lib/origami/trailer.rb +144 -158
  113. data/lib/origami/tree.rb +62 -0
  114. data/lib/origami/version.rb +23 -0
  115. data/lib/origami/webcapture.rb +88 -79
  116. data/lib/origami/xfa.rb +2863 -2882
  117. data/lib/origami/xreftable.rb +472 -384
  118. data/test/dataset/calc.pdf +85 -0
  119. data/test/dataset/crypto.pdf +82 -0
  120. data/test/dataset/empty.pdf +49 -0
  121. data/test/test_actions.rb +27 -0
  122. data/test/test_annotations.rb +90 -0
  123. data/test/test_pages.rb +31 -0
  124. data/test/test_pdf.rb +16 -0
  125. data/test/test_pdf_attachment.rb +34 -0
  126. data/test/test_pdf_create.rb +24 -0
  127. data/test/test_pdf_encrypt.rb +95 -0
  128. data/test/test_pdf_parse.rb +96 -0
  129. data/test/test_pdf_sign.rb +58 -0
  130. data/test/test_streams.rb +182 -0
  131. data/test/test_xrefs.rb +67 -0
  132. metadata +88 -58
  133. data/README +0 -67
  134. data/bin/pdf2graph +0 -121
  135. data/bin/pdfcocoon +0 -104
  136. data/lib/origami/file.rb +0 -233
  137. data/samples/README.txt +0 -45
  138. data/samples/actions/launch/calc.rb +0 -87
  139. data/samples/actions/launch/winparams.rb +0 -22
  140. data/samples/actions/loop/loopgoto.rb +0 -24
  141. data/samples/actions/loop/loopnamed.rb +0 -21
  142. data/samples/actions/named/named.rb +0 -31
  143. data/samples/actions/samba/smbrelay.rb +0 -26
  144. data/samples/actions/webbug/submitform.js +0 -26
  145. data/samples/actions/webbug/webbug-browser.rb +0 -68
  146. data/samples/actions/webbug/webbug-js.rb +0 -67
  147. data/samples/actions/webbug/webbug-reader.rb +0 -90
  148. data/samples/attachments/attach.rb +0 -40
  149. data/samples/attachments/attached.txt +0 -1
  150. data/samples/crypto/crypto.rb +0 -28
  151. data/samples/digsig/signed.rb +0 -46
  152. data/samples/exploits/cve-2008-2992-utilprintf.rb +0 -87
  153. data/samples/exploits/cve-2009-0927-geticon.rb +0 -65
  154. data/samples/exploits/exploit_customdictopen.rb +0 -55
  155. data/samples/exploits/getannots.rb +0 -69
  156. data/samples/flash/flash.rb +0 -31
  157. data/samples/javascript/attached.txt +0 -1
  158. data/samples/javascript/js.rb +0 -52
  159. data/templates/patterns.rb +0 -66
  160. data/templates/widgets.rb +0 -173
  161. data/templates/xdp.rb +0 -92
  162. data/test/ts_pdf.rb +0 -50
@@ -1,104 +1,98 @@
1
1
  =begin
2
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 AT security-labs DOT 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/>.
3
+ This file is part of Origami, PDF manipulation framework for Ruby
4
+ Copyright (C) 2016 Guillaume Delugré.
5
+
6
+ Origami is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Lesser General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ Origami is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public License
17
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
23
18
 
24
19
  =end
25
20
 
26
21
  module Origami
27
22
 
28
- class InvalidPDFInstructionError < Exception ; end
29
- class PDF::Instruction
30
- attr_reader :operator
31
- attr_accessor :operands
23
+ class InvalidPDFInstructionError < Error; end
32
24
 
33
- @@regexp = Regexp.new('([^ \\t\\r\\n\\0\\[\\]<>()%\\/]+)')
34
- @insns = Hash.new(:operands => [], :render => lambda{})
25
+ class PDF::Instruction
26
+ using TypeConversion
35
27
 
36
- def initialize(operator, *operands)
37
- @operator = operator
38
- @operands = operands.map!{|arg| arg.is_a?(Origami::Object) ? arg.value : arg}
28
+ attr_reader :operator
29
+ attr_accessor :operands
39
30
 
40
- if self.class.has_op?(operator)
41
- opdef = self.class.get_operands(operator)
31
+ @insns = Hash.new(operands: [], render: lambda{})
42
32
 
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
33
+ def initialize(operator, *operands)
34
+ @operator = operator
35
+ @operands = operands.map!{|arg| arg.is_a?(Origami::Object) ? arg.value : arg}
49
36
 
50
- def render(canvas)
51
- self.class.get_render_proc(@operator)[canvas, *@operands]
37
+ if self.class.has_op?(operator)
38
+ opdef = self.class.get_operands(operator)
52
39
 
53
- self
54
- end
40
+ if not opdef.include?('*') and opdef.size != operands.size
41
+ raise InvalidPDFInstructionError,
42
+ "Numbers of operands mismatch for #{operator}: #{operands.inspect}"
43
+ end
44
+ end
45
+ end
55
46
 
56
- def to_s
57
- "#{operands.map{|op| op.to_o.to_s}.join(' ')}#{' ' unless operands.empty?}#{operator}\n"
58
- end
47
+ def render(canvas)
48
+ self.class.get_render_proc(@operator)[canvas, *@operands]
59
49
 
60
- class << self
61
- def insn(operator, *operands, &render_proc)
62
- @insns[operator] = {}
63
- @insns[operator][:operands] = operands
64
- @insns[operator][:render] = render_proc || lambda{}
65
- end
66
-
67
- def has_op?(operator)
68
- @insns.has_key? operator
69
- end
70
-
71
- def get_render_proc(operator)
72
- @insns[operator][:render]
73
- end
74
-
75
- def get_operands(operator)
76
- @insns[operator][:operands]
77
- end
78
-
79
- def parse(stream)
80
- operands = []
81
- while type = Object.typeof(stream, true)
82
- operands.push type.parse(stream)
50
+ self
83
51
  end
84
-
85
- if not stream.eos?
86
- if stream.scan(@@regexp).nil?
87
- raise InvalidPDFInstructionError,
88
- "Operator: #{(stream.peek(10) + '...').inspect}"
89
- end
90
-
91
- operator = stream[1]
92
- PDF::Instruction.new(operator, *operands)
93
- else
94
- if not operands.empty?
95
- raise InvalidPDFInstructionError,
96
- "No operator given for operands: #{operands.join}"
97
- end
52
+
53
+ def to_s
54
+ "#{operands.map{|op| op.to_o.to_s}.join(' ')}#{' ' unless operands.empty?}#{operator}\n"
98
55
  end
99
- end
100
- end
101
56
 
102
- end
103
- end
57
+ class << self
58
+ def insn(operator, *operands, &render_proc)
59
+ @insns[operator] = {}
60
+ @insns[operator][:operands] = operands
61
+ @insns[operator][:render] = render_proc || lambda{}
62
+ end
63
+
64
+ def has_op?(operator)
65
+ @insns.has_key? operator
66
+ end
67
+
68
+ def get_render_proc(operator)
69
+ @insns[operator][:render]
70
+ end
71
+
72
+ def get_operands(operator)
73
+ @insns[operator][:operands]
74
+ end
75
+
76
+ def parse(stream)
77
+ operands = []
78
+ while type = Object.typeof(stream, true)
79
+ operands.push type.parse(stream)
80
+ end
81
+
82
+ if not stream.eos?
83
+ if stream.scan(/(?<operator>[[:graph:]&&[^\[\]<>()%\/]]+)/).nil?
84
+ raise InvalidPDFInstructionError, "Operator: #{(stream.peek(10) + '...').inspect}"
85
+ end
86
+
87
+ operator = stream['operator']
88
+ PDF::Instruction.new(operator, *operands)
89
+ else
90
+ unless operands.empty?
91
+ raise InvalidPDFInstructionError, "No operator given for operands: #{operands.map(&:to_s).join(' ')}"
92
+ end
93
+ end
94
+ end
95
+ end
104
96
 
97
+ end
98
+ end
@@ -1,188 +1,182 @@
1
1
  =begin
2
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 AT security-labs DOT 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/>.
3
+ This file is part of Origami, PDF manipulation framework for Ruby
4
+ Copyright (C) 2016 Guillaume Delugré.
5
+
6
+ Origami is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Lesser General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ Origami is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public License
17
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
23
18
 
24
19
  =end
25
20
 
26
21
  module Origami
27
22
 
28
- module Graphics
23
+ module Graphics
29
24
 
30
- module LineCapStyle
31
- BUTT_CAP = 0
32
- ROUND_CAP = 1
33
- PROJECTING_SQUARE_CAP = 2
34
- end
25
+ module LineCapStyle
26
+ BUTT_CAP = 0
27
+ ROUND_CAP = 1
28
+ PROJECTING_SQUARE_CAP = 2
29
+ end
35
30
 
36
- module LineJoinStyle
37
- MITER_JOIN = 0
38
- ROUND_JOIN = 1
39
- BEVEL_JOIN = 2
40
- end
31
+ module LineJoinStyle
32
+ MITER_JOIN = 0
33
+ ROUND_JOIN = 1
34
+ BEVEL_JOIN = 2
35
+ end
41
36
 
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
37
+ class DashPattern
38
+ attr_accessor :array, :phase
58
39
 
59
- class InvalidPathError < Exception; end
60
- class Path
40
+ def initialize(array, phase = 0)
41
+ @array = array
42
+ @phase = phase
43
+ end
61
44
 
62
- module Segment
63
- attr_accessor :from, :to
45
+ def eql?(dash) #:nodoc
46
+ dash.array == @array and dash.phase == @phase
47
+ end
64
48
 
65
- def initialize(from, to)
66
- @from, @to = from, to
49
+ def hash #:nodoc:
50
+ [ @array, @phase ].hash
51
+ end
67
52
  end
68
- end
69
53
 
70
- class Line
71
- include Segment
72
- end
73
-
74
- attr_accessor :current_point
75
- attr_reader :segments
54
+ class InvalidPathError < Error #:nodoc:
55
+ end
76
56
 
77
- def initialize
78
- @segments = []
79
- @current_point = nil
80
- @closed = false
81
- end
57
+ class Path
58
+ module Segment
59
+ attr_accessor :from, :to
82
60
 
83
- def is_closed?
84
- @closed
85
- end
61
+ def initialize(from, to)
62
+ @from, @to = from, to
63
+ end
64
+ end
86
65
 
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
66
+ class Line
67
+ include Segment
68
+ end
95
69
 
96
- def add_segment(seg)
97
- raise GraphicsStateError, "Cannot modify closed subpath" if is_closed?
70
+ attr_accessor :current_point
71
+ attr_reader :segments
98
72
 
99
- @segments << seg
100
- @current_point = seg.to
101
- end
73
+ def initialize
74
+ @segments = []
75
+ @current_point = nil
76
+ @closed = false
77
+ end
102
78
 
103
- end
79
+ def is_closed?
80
+ @closed
81
+ end
104
82
 
105
- end
83
+ def close!
84
+ from = @current_point
85
+ to = @segments.first.from
106
86
 
107
- class PDF::Instruction
108
- insn 'm', Real, Real do |canvas, x,y|
109
- canvas.gs.current_path << (subpath = Graphics::Path.new)
110
- subpath.current_point = [x,y]
87
+ @segments << Line.new(from, to)
88
+ @segments.freeze
89
+ @closed = true
90
+ end
91
+
92
+ def add_segment(seg)
93
+ raise GraphicsStateError, "Cannot modify closed subpath" if is_closed?
94
+
95
+ @segments << seg
96
+ @current_point = seg.to
97
+ end
98
+ end
111
99
  end
112
100
 
113
- insn 'l', Real, Real do |canvas, x,y|
114
- if canvas.gs.current_path.empty?
115
- raise InvalidPathError, "No current point is defined"
116
- end
101
+ class PDF::Instruction
102
+ insn 'm', Real, Real do |canvas, x,y|
103
+ canvas.gs.current_path << (subpath = Graphics::Path.new)
104
+ subpath.current_point = [x,y]
105
+ end
117
106
 
118
- subpath = canvas.gs.current_path.last
107
+ insn 'l', Real, Real do |canvas, x,y|
108
+ if canvas.gs.current_path.empty?
109
+ raise InvalidPathError, "No current point is defined"
110
+ end
119
111
 
120
- from = subpath.current_point
121
- to = [x,y]
122
- subpath.add_segment(Graphics::Path::Line.new(from, to))
123
- end
112
+ subpath = canvas.gs.current_path.last
124
113
 
125
- insn 'h' do |canvas|
126
- unless canvas.gs.current_path.empty?
127
- subpath = canvas.gs.current_path.last
128
- subpath.close! unless subpath.is_closed?
129
- end
130
- end
114
+ from = subpath.current_point
115
+ to = [x,y]
116
+ subpath.add_segment(Graphics::Path::Line.new(from, to))
117
+ end
131
118
 
132
- insn 're', Real, Real, Real, Real do |canvas, x,y,width,height|
133
- tx = x + width
134
- ty = y + height
135
- canvas.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
119
+ insn 'h' do |canvas|
120
+ unless canvas.gs.current_path.empty?
121
+ subpath = canvas.gs.current_path.last
122
+ subpath.close! unless subpath.is_closed?
123
+ end
124
+ end
141
125
 
142
- insn 'S' do |canvas|
143
- canvas.stroke_path
144
- end
126
+ insn 're', Real, Real, Real, Real do |canvas, x,y,width,height|
127
+ tx = x + width
128
+ ty = y + height
129
+ canvas.gs.current_path << (subpath = Graphics::Path.new)
130
+ subpath.segments << Graphics::Path::Line.new([x,y], [tx,y])
131
+ subpath.segments << Graphics::Path::Line.new([tx,y], [tx, ty])
132
+ subpath.segments << Graphics::Path::Line.new([tx, ty], [x, ty])
133
+ subpath.close!
134
+ end
145
135
 
146
- insn 's' do |canvas|
147
- canvas.gs.current_path.last.close!
148
- canvas.stroke_path
149
- end
136
+ insn 'S' do |canvas|
137
+ canvas.stroke_path
138
+ end
150
139
 
151
- insn 'f' do |canvas|
152
- canvas.fill_path
153
- end
140
+ insn 's' do |canvas|
141
+ canvas.gs.current_path.last.close!
142
+ canvas.stroke_path
143
+ end
154
144
 
155
- insn 'F' do |canvas|
156
- canvas.fill_path
157
- end
145
+ insn 'f' do |canvas|
146
+ canvas.fill_path
147
+ end
158
148
 
159
- insn 'f*' do |canvas|
160
- canvas.fill_path
161
- end
149
+ insn 'F' do |canvas|
150
+ canvas.fill_path
151
+ end
162
152
 
163
- insn 'B' do |canvas|
164
- canvas.fill_path
165
- canvas.stroke_path
166
- end
153
+ insn 'f*' do |canvas|
154
+ canvas.fill_path
155
+ end
167
156
 
168
- insn 'B*' do |canvas|
169
- canvas.fill_path
170
- canvas.stroke_path
171
- end
157
+ insn 'B' do |canvas|
158
+ canvas.fill_path
159
+ canvas.stroke_path
160
+ end
172
161
 
173
- insn 'b' do |canvas|
174
- canvas.gs.current_path.last.close!
175
- canvas.fill_path
176
- canvas.stroke_path
177
- end
178
-
179
- insn 'b*' do |canvas|
180
- canvas.gs.current_path.last.close!
181
- canvas.fill_path
182
- canvas.stroke_path
162
+ insn 'B*' do |canvas|
163
+ canvas.fill_path
164
+ canvas.stroke_path
165
+ end
166
+
167
+ insn 'b' do |canvas|
168
+ canvas.gs.current_path.last.close!
169
+ canvas.fill_path
170
+ canvas.stroke_path
171
+ end
172
+
173
+ insn 'b*' do |canvas|
174
+ canvas.gs.current_path.last.close!
175
+ canvas.fill_path
176
+ canvas.stroke_path
177
+ end
178
+
179
+ insn 'n'
183
180
  end
184
-
185
- insn 'n'
186
- end
187
181
 
188
182
  end