origami 1.2.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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