origami 2.0.0 → 2.0.1
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.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/bin/gui/config.rb +2 -1
- data/bin/gui/file.rb +118 -240
- data/bin/gui/gtkhex.rb +5 -5
- data/bin/gui/hexview.rb +20 -16
- data/bin/gui/imgview.rb +1 -1
- data/bin/gui/menu.rb +138 -158
- data/bin/gui/properties.rb +46 -48
- data/bin/gui/signing.rb +183 -214
- data/bin/gui/textview.rb +1 -1
- data/bin/gui/treeview.rb +13 -7
- data/bin/gui/walker.rb +102 -71
- data/bin/gui/xrefs.rb +1 -1
- data/bin/pdf2ruby +3 -3
- data/bin/pdfcop +18 -11
- data/bin/pdfextract +14 -5
- data/bin/pdfmetadata +3 -3
- data/bin/shell/console.rb +8 -8
- data/bin/shell/hexdump.rb +4 -4
- data/examples/attachments/nested_document.rb +1 -1
- data/examples/javascript/hello_world.rb +3 -3
- data/lib/origami.rb +0 -1
- data/lib/origami/acroform.rb +3 -3
- data/lib/origami/array.rb +1 -3
- data/lib/origami/boolean.rb +1 -3
- data/lib/origami/catalog.rb +3 -9
- data/lib/origami/destinations.rb +2 -2
- data/lib/origami/dictionary.rb +15 -29
- data/lib/origami/encryption.rb +334 -692
- data/lib/origami/extensions/fdf.rb +3 -2
- data/lib/origami/extensions/ppklite.rb +5 -9
- data/lib/origami/filespec.rb +2 -2
- data/lib/origami/filters.rb +54 -36
- data/lib/origami/filters/ascii.rb +67 -49
- data/lib/origami/filters/ccitt.rb +4 -236
- data/lib/origami/filters/ccitt/tables.rb +267 -0
- data/lib/origami/filters/crypt.rb +1 -1
- data/lib/origami/filters/dct.rb +0 -1
- data/lib/origami/filters/flate.rb +3 -43
- data/lib/origami/filters/lzw.rb +62 -99
- data/lib/origami/filters/predictors.rb +135 -105
- data/lib/origami/filters/runlength.rb +34 -22
- data/lib/origami/graphics.rb +2 -2
- data/lib/origami/graphics/colors.rb +89 -63
- data/lib/origami/graphics/path.rb +14 -14
- data/lib/origami/graphics/patterns.rb +31 -33
- data/lib/origami/graphics/render.rb +0 -1
- data/lib/origami/graphics/state.rb +9 -9
- data/lib/origami/graphics/text.rb +17 -17
- data/lib/origami/graphics/xobject.rb +102 -92
- data/lib/origami/javascript.rb +91 -68
- data/lib/origami/linearization.rb +22 -20
- data/lib/origami/metadata.rb +1 -1
- data/lib/origami/name.rb +1 -3
- data/lib/origami/null.rb +1 -3
- data/lib/origami/numeric.rb +3 -13
- data/lib/origami/object.rb +100 -72
- data/lib/origami/page.rb +24 -28
- data/lib/origami/parser.rb +34 -51
- data/lib/origami/parsers/fdf.rb +2 -2
- data/lib/origami/parsers/pdf.rb +41 -18
- data/lib/origami/parsers/pdf/lazy.rb +83 -46
- data/lib/origami/parsers/pdf/linear.rb +19 -10
- data/lib/origami/parsers/ppklite.rb +1 -1
- data/lib/origami/pdf.rb +150 -206
- data/lib/origami/reference.rb +4 -6
- data/lib/origami/signature.rb +76 -48
- data/lib/origami/stream.rb +69 -63
- data/lib/origami/string.rb +2 -19
- data/lib/origami/trailer.rb +25 -22
- data/lib/origami/version.rb +1 -1
- data/lib/origami/xfa.rb +6 -4
- data/lib/origami/xreftable.rb +29 -29
- data/test/test_annotations.rb +16 -38
- data/test/test_pdf_attachment.rb +1 -1
- data/test/test_pdf_parse.rb +1 -1
- data/test/test_xrefs.rb +2 -2
- metadata +4 -4
- data/lib/origami/export.rb +0 -247
@@ -99,12 +99,12 @@ module Origami
|
|
99
99
|
end
|
100
100
|
|
101
101
|
class PDF::Instruction
|
102
|
-
insn
|
102
|
+
insn 'm', Real, Real do |canvas, x,y|
|
103
103
|
canvas.gs.current_path << (subpath = Graphics::Path.new)
|
104
104
|
subpath.current_point = [x,y]
|
105
105
|
end
|
106
106
|
|
107
|
-
insn
|
107
|
+
insn 'l', Real, Real do |canvas, x,y|
|
108
108
|
if canvas.gs.current_path.empty?
|
109
109
|
raise InvalidPathError, "No current point is defined"
|
110
110
|
end
|
@@ -116,14 +116,14 @@ module Origami
|
|
116
116
|
subpath.add_segment(Graphics::Path::Line.new(from, to))
|
117
117
|
end
|
118
118
|
|
119
|
-
insn
|
119
|
+
insn 'h' do |canvas|
|
120
120
|
unless canvas.gs.current_path.empty?
|
121
121
|
subpath = canvas.gs.current_path.last
|
122
122
|
subpath.close! unless subpath.is_closed?
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
-
insn
|
126
|
+
insn 're', Real, Real, Real, Real do |canvas, x,y,width,height|
|
127
127
|
tx = x + width
|
128
128
|
ty = y + height
|
129
129
|
canvas.gs.current_path << (subpath = Graphics::Path.new)
|
@@ -133,50 +133,50 @@ module Origami
|
|
133
133
|
subpath.close!
|
134
134
|
end
|
135
135
|
|
136
|
-
insn
|
136
|
+
insn 'S' do |canvas|
|
137
137
|
canvas.stroke_path
|
138
138
|
end
|
139
139
|
|
140
|
-
insn
|
140
|
+
insn 's' do |canvas|
|
141
141
|
canvas.gs.current_path.last.close!
|
142
142
|
canvas.stroke_path
|
143
143
|
end
|
144
144
|
|
145
|
-
insn
|
145
|
+
insn 'f' do |canvas|
|
146
146
|
canvas.fill_path
|
147
147
|
end
|
148
148
|
|
149
|
-
insn
|
149
|
+
insn 'F' do |canvas|
|
150
150
|
canvas.fill_path
|
151
151
|
end
|
152
152
|
|
153
|
-
insn
|
153
|
+
insn 'f*' do |canvas|
|
154
154
|
canvas.fill_path
|
155
155
|
end
|
156
156
|
|
157
|
-
insn
|
157
|
+
insn 'B' do |canvas|
|
158
158
|
canvas.fill_path
|
159
159
|
canvas.stroke_path
|
160
160
|
end
|
161
161
|
|
162
|
-
insn
|
162
|
+
insn 'B*' do |canvas|
|
163
163
|
canvas.fill_path
|
164
164
|
canvas.stroke_path
|
165
165
|
end
|
166
166
|
|
167
|
-
insn
|
167
|
+
insn 'b' do |canvas|
|
168
168
|
canvas.gs.current_path.last.close!
|
169
169
|
canvas.fill_path
|
170
170
|
canvas.stroke_path
|
171
171
|
end
|
172
172
|
|
173
|
-
insn
|
173
|
+
insn 'b*' do |canvas|
|
174
174
|
canvas.gs.current_path.last.close!
|
175
175
|
canvas.fill_path
|
176
176
|
canvas.stroke_path
|
177
177
|
end
|
178
178
|
|
179
|
-
insn
|
179
|
+
insn 'n'
|
180
180
|
end
|
181
181
|
|
182
182
|
end
|
@@ -51,11 +51,11 @@ module Origami
|
|
51
51
|
field :PatternType, :Type => Integer, :Default => Pattern::Type::TILING, :Required => true
|
52
52
|
field :PaintType, :Type => Integer, :Required => true
|
53
53
|
field :TilingType, :Type => Integer, :Required => true
|
54
|
-
field :BBox, :Type =>
|
54
|
+
field :BBox, :Type => Rectangle, :Required => true
|
55
55
|
field :XStep, :Type => Number, :Required => true
|
56
56
|
field :YStep, :Type => Number, :Required => true
|
57
57
|
field :Resources, :Type => Resources, :Required => true
|
58
|
-
field :Matrix, :Type => Array, :Default => [ 1, 0, 0, 1, 0, 0 ]
|
58
|
+
field :Matrix, :Type => Array.of(Number, length: 6), :Default => [ 1, 0, 0, 1, 0, 0 ]
|
59
59
|
end
|
60
60
|
|
61
61
|
class Shading < Dictionary
|
@@ -63,37 +63,48 @@ module Origami
|
|
63
63
|
include Pattern
|
64
64
|
|
65
65
|
module Type
|
66
|
-
|
66
|
+
FUNCTION_BASED = 1
|
67
67
|
AXIAL = 2
|
68
68
|
RADIAL = 3
|
69
69
|
FREEFORM_TRIANGLE_MESH = 4
|
70
70
|
LATTICEFORM_TRIANGLE_MESH = 5
|
71
71
|
COONS_PATCH_MESH = 6
|
72
|
-
TENSORPRODUCT_PATCH_MESH
|
72
|
+
TENSORPRODUCT_PATCH_MESH = 7
|
73
73
|
end
|
74
74
|
|
75
75
|
field :PatternType, :Type => Integer, :Default => Pattern::Type::SHADING, :Required => true
|
76
76
|
field :Shading, :Type => [ Dictionary, Stream ], :Required => true
|
77
|
-
field :Matrix, :Type => Array, :Default => [ 1, 0, 0, 1, 0, 0 ]
|
78
|
-
field :ExtGState, :Type =>
|
77
|
+
field :Matrix, :Type => Array.of(Number, length: 6), :Default => [ 1, 0, 0, 1, 0, 0 ]
|
78
|
+
field :ExtGState, :Type => ExtGState
|
79
79
|
|
80
|
+
# Fields common to all shading objects.
|
80
81
|
module ShadingObject
|
81
82
|
def self.included(receiver)
|
82
83
|
receiver.field :ShadingType, :Type => Integer, :Required => true
|
83
84
|
receiver.field :ColorSpace, :Type => [ Name, Array ], :Required => true
|
84
85
|
receiver.field :Background, :Type => Array
|
85
|
-
receiver.field :BBox, :Type =>
|
86
|
+
receiver.field :BBox, :Type => Rectangle
|
86
87
|
receiver.field :AntiAlias, :Type => Boolean, :Default => false
|
87
88
|
end
|
88
89
|
end
|
89
90
|
|
91
|
+
# Fields common to all Mesh shadings.
|
92
|
+
module Mesh
|
93
|
+
def self.included(receiver)
|
94
|
+
receiver.field :BitsPerCoordinate, :Type => Integer, :Required => true
|
95
|
+
receiver.field :BitsPerComponent, :Type => Integer, :Required => true
|
96
|
+
receiver.field :Decode, :Type => Array.of(Number), :Required => true
|
97
|
+
receiver.field :Function, :Type => [ Dictionary, Stream ]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
90
101
|
class FunctionBased < Dictionary
|
91
102
|
include StandardObject
|
92
103
|
include ShadingObject
|
93
104
|
|
94
|
-
field :ShadingType, :Type => Integer, :Default => Shading::Type::
|
95
|
-
field :Domain, :Type => Array, :Default => [ 0.0, 1.0, 0.0, 1.0 ]
|
96
|
-
field :Matrix, :Type => Array, :Default => [ 1, 0, 0, 1, 0, 0 ]
|
105
|
+
field :ShadingType, :Type => Integer, :Default => Shading::Type::FUNCTION_BASED, :Required => true
|
106
|
+
field :Domain, :Type => Array.of(Number, length: 4), :Default => [ 0.0, 1.0, 0.0, 1.0 ]
|
107
|
+
field :Matrix, :Type => Array.of(Number, length: 6), :Default => [ 1, 0, 0, 1, 0, 0 ]
|
97
108
|
field :Function, :Type => [ Dictionary, Stream ], :Required => true
|
98
109
|
end
|
99
110
|
|
@@ -102,10 +113,10 @@ module Origami
|
|
102
113
|
include ShadingObject
|
103
114
|
|
104
115
|
field :ShadingType, :Type => Integer, :Default => Shading::Type::AXIAL, :Required => true
|
105
|
-
field :Coords, :Type => Array, :Required => true
|
106
|
-
field :Domain, :Type => Array, :Default => [ 0.0, 1.0 ]
|
116
|
+
field :Coords, :Type => Array.of(Number, length: 4), :Required => true
|
117
|
+
field :Domain, :Type => Array.of(Number, length: 2), :Default => [ 0.0, 1.0 ]
|
107
118
|
field :Function, :Type => [ Dictionary, Stream ], :Required => true
|
108
|
-
field :Extend, :Type => Array, :Default => [ false, false ]
|
119
|
+
field :Extend, :Type => Array.of(Boolean, length: 2), :Default => [ false, false ]
|
109
120
|
end
|
110
121
|
|
111
122
|
class Radial < Dictionary
|
@@ -113,54 +124,41 @@ module Origami
|
|
113
124
|
include ShadingObject
|
114
125
|
|
115
126
|
field :ShadingType, :Type => Integer, :Default => Shading::Type::RADIAL, :Required => true
|
116
|
-
field :Coords, :Type => Array, :Required => true
|
117
|
-
field :Domain, :Type => Array, :Default => [ 0.0, 1.0 ]
|
127
|
+
field :Coords, :Type => Array.of(Number, length: 6), :Required => true
|
128
|
+
field :Domain, :Type => Array.of(Number, length: 2), :Default => [ 0.0, 1.0 ]
|
118
129
|
field :Function, :Type => [ Dictionary, Stream ], :Required => true
|
119
|
-
field :Extend, :Type => Array, :Default => [ false, false ]
|
130
|
+
field :Extend, :Type => Array.of(Boolean, length: 2), :Default => [ false, false ]
|
120
131
|
end
|
121
132
|
|
122
133
|
class FreeFormTriangleMesh < Stream
|
123
134
|
include ShadingObject
|
135
|
+
include Mesh
|
124
136
|
|
125
137
|
field :ShadingType, :Type => Integer, :Default => Shading::Type::FREEFORM_TRIANGLE_MESH, :Required => true
|
126
|
-
field :BitsPerCoordinate, :Type => Integer, :Required => true
|
127
|
-
field :BitsPerComponent, :Type => Integer, :Required => true
|
128
138
|
field :BitsPerFlag, :Type => Integer, :Required => true
|
129
|
-
field :Decode, :Type => Array, :Required => true
|
130
|
-
field :Function, :Type => [ Dictionary, Stream ]
|
131
139
|
end
|
132
140
|
|
133
141
|
class LatticeFormTriangleMesh < Stream
|
134
142
|
include ShadingObject
|
143
|
+
include Mesh
|
135
144
|
|
136
145
|
field :ShadingType, :Type => Integer, :Default => Shading::Type::LATTICEFORM_TRIANGLE_MESH, :Required => true
|
137
|
-
field :BitsPerCoordinate, :Type => Integer, :Required => true
|
138
|
-
field :BitsPerComponent, :Type => Integer, :Required => true
|
139
146
|
field :VerticesPerRow, :Type => Integer, :Required => true
|
140
|
-
field :Decode, :Type => Array, :Required => true
|
141
|
-
field :Function, :Type => [ Dictionary, Stream ]
|
142
147
|
end
|
143
148
|
|
144
149
|
class CoonsPathMesh < Stream
|
145
150
|
include ShadingObject
|
151
|
+
include Mesh
|
146
152
|
|
147
153
|
field :ShadingType, :Type => Integer, :Default => Shading::Type::COONS_PATCH_MESH, :Required => true
|
148
|
-
field :BitsPerCoordinate, :Type => Integer, :Required => true
|
149
|
-
field :BitsPerComponent, :Type => Integer, :Required => true
|
150
154
|
field :BitsPerFlag, :Type => Integer, :Required => true
|
151
|
-
field :Decode, :Type => Array, :Required => true
|
152
|
-
field :Function, :Type => [ Dictionary, Stream ]
|
153
155
|
end
|
154
156
|
|
155
157
|
class TensorProductPatchMesh < Stream
|
156
158
|
include ShadingObject
|
157
159
|
|
158
160
|
field :ShadingType, :Type => Integer, :Default => Shading::Type::TENSORPRODUCT_PATCH_MESH, :Required => true
|
159
|
-
field :BitsPerCoordinate, :Type => Integer, :Required => true
|
160
|
-
field :BitsPerComponent, :Type => Integer, :Required => true
|
161
161
|
field :BitsPerFlag, :Type => Integer, :Required => true
|
162
|
-
field :Decode, :Type => Array, :Required => true
|
163
|
-
field :Function, :Type => [ Dictionary, Stream ]
|
164
162
|
end
|
165
163
|
end
|
166
164
|
|
@@ -168,7 +166,7 @@ module Origami
|
|
168
166
|
end
|
169
167
|
|
170
168
|
class PDF::Instruction
|
171
|
-
insn
|
169
|
+
insn 'sh', Name
|
172
170
|
end
|
173
171
|
|
174
172
|
end
|
@@ -133,17 +133,17 @@ module Origami
|
|
133
133
|
end #module Graphics
|
134
134
|
|
135
135
|
class PDF::Instruction
|
136
|
-
insn
|
137
|
-
insn
|
138
|
-
insn
|
139
|
-
insn
|
140
|
-
insn
|
141
|
-
insn
|
142
|
-
|
143
|
-
insn
|
136
|
+
insn 'q' do |canvas| canvas.gs.save; canvas.gs.reset end
|
137
|
+
insn 'Q' do |canvas| canvas.gs.restore end
|
138
|
+
insn 'w', Real do |canvas, lw| canvas.gs.line_width = lw end
|
139
|
+
insn 'J', Real do |canvas, lc| canvas.gs.line_cap = lc end
|
140
|
+
insn 'j', Real do |canvas, lj| canvas.gs.line_join = lj end
|
141
|
+
insn 'M', Real do |canvas, ml| canvas.gs.miter_limit = ml end
|
142
|
+
|
143
|
+
insn 'd', Array, Integer do |canvas, array, phase|
|
144
144
|
canvas.gs.dash_pattern = Graphics::DashPattern.new array, phase
|
145
145
|
end
|
146
146
|
|
147
|
-
insn
|
147
|
+
insn 'ri', Name do |canvas, ri| canvas.gs.rendering_intent = ri end
|
148
148
|
end
|
149
149
|
end
|
@@ -109,22 +109,22 @@ module Origami
|
|
109
109
|
#
|
110
110
|
# Text instructions definitions
|
111
111
|
#
|
112
|
-
insn
|
113
|
-
insn
|
114
|
-
insn
|
115
|
-
insn
|
112
|
+
insn 'Tc', Real do |canvas, cS| canvas.gs.text_state.char_spacing = cS end
|
113
|
+
insn 'Tw', Real do |canvas, wS| canvas.gs.text_state.word_spacing = wS end
|
114
|
+
insn 'Tz', Real do |canvas, s| canvas.gs.text_state.scaling = s end
|
115
|
+
insn 'TL', Real do |canvas, l| canvas.gs.text_state.leading = l end
|
116
116
|
|
117
|
-
insn
|
117
|
+
insn 'Tf', Name, Real do |canvas, font, size|
|
118
118
|
canvas.gs.text_state.font = font
|
119
119
|
canvas.gs.text_state.font_size = size
|
120
120
|
end
|
121
121
|
|
122
|
-
insn
|
123
|
-
insn
|
124
|
-
insn
|
125
|
-
insn
|
122
|
+
insn 'Tr', Integer do |canvas, r| canvas.gs.text_state.rendering_mode = r end
|
123
|
+
insn 'Ts', Real do |canvas, s| canvas.gs.text_state.text_rise = s end
|
124
|
+
insn 'BT' do |canvas| canvas.gs.text_state.begin_text_object end
|
125
|
+
insn 'ET' do |canvas| canvas.gs.text_state.end_text_object end
|
126
126
|
|
127
|
-
insn
|
127
|
+
insn 'Td', Real, Real do |canvas, tx, ty|
|
128
128
|
unless canvas.gs.text_state.is_in_text_object?
|
129
129
|
raise TextStateError, "Must be in a text object to use operator : Td"
|
130
130
|
end
|
@@ -134,7 +134,7 @@ module Origami
|
|
134
134
|
Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix
|
135
135
|
end
|
136
136
|
|
137
|
-
insn
|
137
|
+
insn 'TD', Real, Real do |canvas, tx, ty|
|
138
138
|
unless canvas.gs.text_state.is_in_text_object?
|
139
139
|
raise TextStateError, "Must be in a text object to use operator : TD"
|
140
140
|
end
|
@@ -146,7 +146,7 @@ module Origami
|
|
146
146
|
Matrix.rows([[1,0,0],[0,1,0],[tx,ty,1]]) * canvas.gs.text_state.text_line_matrix
|
147
147
|
end
|
148
148
|
|
149
|
-
insn
|
149
|
+
insn 'Tm', Real, Real, Real, Real, Real, Real do |canvas, a, b, c, d, e, f|
|
150
150
|
unless canvas.gs.text_state.is_in_text_object?
|
151
151
|
raise TextStateError, "Must be in a text object to use operator : Tm"
|
152
152
|
end
|
@@ -156,7 +156,7 @@ module Origami
|
|
156
156
|
Matrix.rows([[a,b,0],[c,d,0],[e,f,1]])
|
157
157
|
end
|
158
158
|
|
159
|
-
insn
|
159
|
+
insn 'T*' do |canvas|
|
160
160
|
unless canvas.gs.text_state.is_in_text_object?
|
161
161
|
raise TextStateError, "Must be in a text object to use operator : T*"
|
162
162
|
end
|
@@ -168,7 +168,7 @@ module Origami
|
|
168
168
|
Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix
|
169
169
|
end
|
170
170
|
|
171
|
-
insn
|
171
|
+
insn 'Tj', String do |canvas, s|
|
172
172
|
unless canvas.gs.text_state.is_in_text_object?
|
173
173
|
raise TextStateError, "Must be in a text object to use operator : Tj"
|
174
174
|
end
|
@@ -176,7 +176,7 @@ module Origami
|
|
176
176
|
canvas.write_text(s)
|
177
177
|
end
|
178
178
|
|
179
|
-
insn
|
179
|
+
insn "'", String do |canvas, s|
|
180
180
|
unless canvas.gs.text_state.is_in_text_object?
|
181
181
|
raise TextStateError, "Must be in a text object to use operator : '"
|
182
182
|
end
|
@@ -190,7 +190,7 @@ module Origami
|
|
190
190
|
canvas.write_text(s)
|
191
191
|
end
|
192
192
|
|
193
|
-
insn
|
193
|
+
insn '"', Real, Real, String do |canvas, w, c, s|
|
194
194
|
unless canvas.gs.text_state.is_in_text_object?
|
195
195
|
raise TextStateError, "Must be in a text object to use operator : \""
|
196
196
|
end
|
@@ -207,7 +207,7 @@ module Origami
|
|
207
207
|
canvas.write_text(s)
|
208
208
|
end
|
209
209
|
|
210
|
-
insn
|
210
|
+
insn 'TJ', Array do |canvas, arr|
|
211
211
|
arr.each do |g|
|
212
212
|
case g
|
213
213
|
when Fixnum,Float then
|
@@ -45,7 +45,7 @@ module Origami
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def render(engine)
|
48
|
-
load!
|
48
|
+
load!
|
49
49
|
|
50
50
|
@instructions.each do |instruction|
|
51
51
|
instruction.render(engine)
|
@@ -67,13 +67,13 @@ module Origami
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def instructions
|
70
|
-
load!
|
70
|
+
load!
|
71
71
|
|
72
72
|
@instructions
|
73
73
|
end
|
74
74
|
|
75
75
|
def draw_image(name, attr = {})
|
76
|
-
load!
|
76
|
+
load!
|
77
77
|
|
78
78
|
x, y = attr[:x], attr[:y]
|
79
79
|
|
@@ -94,14 +94,14 @@ module Origami
|
|
94
94
|
# Draw a polygon from a array of coordinates.
|
95
95
|
#
|
96
96
|
def draw_polygon(coords = [], attr = {})
|
97
|
-
load!
|
97
|
+
load!
|
98
98
|
|
99
|
-
stroke_color = attr
|
100
|
-
fill_color = attr
|
101
|
-
line_cap = attr
|
102
|
-
line_join = attr
|
103
|
-
line_width = attr
|
104
|
-
dash_pattern = attr
|
99
|
+
stroke_color = attr.fetch(:stroke_color, DEFAULT_STROKE_COLOR)
|
100
|
+
fill_color = attr.fetch(:fill_color, DEFAULT_FILL_COLOR)
|
101
|
+
line_cap = attr.fetch(:line_cap, DEFAULT_LINECAP)
|
102
|
+
line_join = attr.fetch(:line_join, DEFAULT_LINEJOIN)
|
103
|
+
line_width = attr.fetch(:line_width, DEFAULT_LINEWIDTH)
|
104
|
+
dash_pattern = attr.fetch(:dash, DEFAULT_DASHPATTERN)
|
105
105
|
|
106
106
|
stroke = attr[:stroke].nil? ? true : attr[:stroke]
|
107
107
|
fill = attr[:fill].nil? ? false : attr[:fill]
|
@@ -147,14 +147,14 @@ module Origami
|
|
147
147
|
# Draw a rectangle at position (_x_,_y_) with defined _width_ and _height_.
|
148
148
|
#
|
149
149
|
def draw_rectangle(x, y, width, height, attr = {})
|
150
|
-
load!
|
150
|
+
load!
|
151
151
|
|
152
|
-
stroke_color = attr
|
153
|
-
fill_color = attr
|
154
|
-
line_cap = attr
|
155
|
-
line_join = attr
|
156
|
-
line_width = attr
|
157
|
-
dash_pattern = attr
|
152
|
+
stroke_color = attr.fetch(:stroke_color, DEFAULT_STROKE_COLOR)
|
153
|
+
fill_color = attr.fetch(:fill_color, DEFAULT_FILL_COLOR)
|
154
|
+
line_cap = attr.fetch(:line_cap, DEFAULT_LINECAP)
|
155
|
+
line_join = attr.fetch(:line_join, DEFAULT_LINEJOIN)
|
156
|
+
line_width = attr.fetch(:line_width, DEFAULT_LINEWIDTH)
|
157
|
+
dash_pattern = attr.fetch(:dash, DEFAULT_DASHPATTERN)
|
158
158
|
|
159
159
|
stroke = attr[:stroke].nil? ? true : attr[:stroke]
|
160
160
|
fill = attr[:fill].nil? ? false : attr[:fill]
|
@@ -195,20 +195,20 @@ module Origami
|
|
195
195
|
# _attr_:: Formatting attributes.
|
196
196
|
#
|
197
197
|
def write(text, attr = {})
|
198
|
-
load!
|
199
|
-
|
200
|
-
x,y
|
201
|
-
font = attr
|
202
|
-
size = attr
|
203
|
-
leading = attr
|
204
|
-
color = attr
|
205
|
-
stroke_color = attr
|
206
|
-
line_width = attr
|
207
|
-
word_spacing = attr
|
208
|
-
char_spacing = attr
|
209
|
-
scale = attr
|
210
|
-
rise = attr
|
211
|
-
rendering = attr
|
198
|
+
load!
|
199
|
+
|
200
|
+
x, y = attr[:x], attr[:y]
|
201
|
+
font = attr.fetch(:font, DEFAULT_FONT)
|
202
|
+
size = attr.fetch(:size, DEFAULT_SIZE)
|
203
|
+
leading = attr.fetch(:leading, DEFAULT_LEADING)
|
204
|
+
color = attr.fetch(:color, attr.fetch(:fill_color, DEFAULT_STROKE_COLOR))
|
205
|
+
stroke_color = attr.fetch(:stroke_color, DEFAULT_STROKE_COLOR)
|
206
|
+
line_width = attr.fetch(:line_width, DEFAULT_LINEWIDTH)
|
207
|
+
word_spacing = attr.fetch(:word_spacing, @canvas.gs.text_state.word_spacing)
|
208
|
+
char_spacing = attr.fetch(:char_spacing, @canvas.gs.text_state.char_spacing)
|
209
|
+
scale = attr.fetch(:scale, @canvas.gs.text_state.scaling)
|
210
|
+
rise = attr.fetch(:rise, @canvas.gs.text_state.text_rise)
|
211
|
+
rendering = attr.fetch(:rendering, @canvas.gs.text_state.rendering_mode)
|
212
212
|
|
213
213
|
@instructions << PDF::Instruction.new('ET').render(@canvas) if (x or y) and @canvas.gs.text_state.is_in_text_object?
|
214
214
|
|
@@ -218,12 +218,12 @@ module Origami
|
|
218
218
|
|
219
219
|
set_text_font(font, size)
|
220
220
|
set_text_pos(x, y) if x or y
|
221
|
-
set_text_leading(leading)
|
222
|
-
set_text_rendering(rendering)
|
223
|
-
set_text_rise(rise)
|
224
|
-
set_text_scale(scale)
|
225
|
-
set_text_word_spacing(word_spacing)
|
226
|
-
set_text_char_spacing(char_spacing)
|
221
|
+
set_text_leading(leading)
|
222
|
+
set_text_rendering(rendering)
|
223
|
+
set_text_rise(rise)
|
224
|
+
set_text_scale(scale)
|
225
|
+
set_text_word_spacing(word_spacing)
|
226
|
+
set_text_char_spacing(char_spacing)
|
227
227
|
set_fill_color(color)
|
228
228
|
set_stroke_color(stroke_color)
|
229
229
|
set_line_width(line_width)
|
@@ -234,14 +234,16 @@ module Origami
|
|
234
234
|
end
|
235
235
|
|
236
236
|
def paint_shading(shade)
|
237
|
-
load!
|
237
|
+
load!
|
238
|
+
|
238
239
|
@instructions << PDF::Instruction.new('sh', shade).render(@canvas)
|
239
240
|
|
240
241
|
self
|
241
242
|
end
|
242
243
|
|
243
244
|
def set_text_font(fontname, size)
|
244
|
-
load!
|
245
|
+
load!
|
246
|
+
|
245
247
|
if fontname != @canvas.gs.text_state.font or size != @canvas.gs.text_state.font_size
|
246
248
|
@instructions << PDF::Instruction.new('Tf', fontname, size).render(@canvas)
|
247
249
|
end
|
@@ -250,14 +252,16 @@ module Origami
|
|
250
252
|
end
|
251
253
|
|
252
254
|
def set_text_pos(tx,ty)
|
253
|
-
load!
|
255
|
+
load!
|
256
|
+
|
254
257
|
@instructions << PDF::Instruction.new('Td', tx, ty).render(@canvas)
|
255
258
|
|
256
259
|
self
|
257
260
|
end
|
258
261
|
|
259
262
|
def set_text_leading(leading)
|
260
|
-
load!
|
263
|
+
load!
|
264
|
+
|
261
265
|
if leading != @canvas.gs.text_state.leading
|
262
266
|
@instructions << PDF::Instruction.new('TL', leading).render(@canvas)
|
263
267
|
end
|
@@ -266,7 +270,8 @@ module Origami
|
|
266
270
|
end
|
267
271
|
|
268
272
|
def set_text_rendering(rendering)
|
269
|
-
load!
|
273
|
+
load!
|
274
|
+
|
270
275
|
if rendering != @canvas.gs.text_state.rendering_mode
|
271
276
|
@instructions << PDF::Instruction.new('Tr', rendering).render(@canvas)
|
272
277
|
end
|
@@ -275,7 +280,8 @@ module Origami
|
|
275
280
|
end
|
276
281
|
|
277
282
|
def set_text_rise(rise)
|
278
|
-
load!
|
283
|
+
load!
|
284
|
+
|
279
285
|
if rise != @canvas.gs.text_state.text_rise
|
280
286
|
@instructions << PDF::Instruction.new('Ts', rise).render(@canvas)
|
281
287
|
end
|
@@ -284,7 +290,8 @@ module Origami
|
|
284
290
|
end
|
285
291
|
|
286
292
|
def set_text_scale(scaling)
|
287
|
-
load!
|
293
|
+
load!
|
294
|
+
|
288
295
|
if scale != @canvas.gs.text_state.scaling
|
289
296
|
@instructions << PDF::Instruction.new('Tz', scaling).render(@canvas)
|
290
297
|
end
|
@@ -293,7 +300,8 @@ module Origami
|
|
293
300
|
end
|
294
301
|
|
295
302
|
def set_text_word_spacing(word_spacing)
|
296
|
-
load!
|
303
|
+
load!
|
304
|
+
|
297
305
|
if word_spacing != @canvas.gs.text_state.word_spacing
|
298
306
|
@instructions << PDF::Instruction.new('Tw', word_spacing).render(@canvas)
|
299
307
|
end
|
@@ -302,7 +310,8 @@ module Origami
|
|
302
310
|
end
|
303
311
|
|
304
312
|
def set_text_char_spacing(char_spacing)
|
305
|
-
load!
|
313
|
+
load!
|
314
|
+
|
306
315
|
if char_spacing != @canvas.gs.text_state.char_spacing
|
307
316
|
@instructions << PDF::Instruction.new('Tc', char_spacing).render(@canvas)
|
308
317
|
end
|
@@ -311,7 +320,7 @@ module Origami
|
|
311
320
|
end
|
312
321
|
|
313
322
|
def set_fill_color(color)
|
314
|
-
load!
|
323
|
+
load!
|
315
324
|
|
316
325
|
@instructions << ( i =
|
317
326
|
if (color.respond_to? :r and color.respond_to? :g and color.respond_to? :b) or (color.is_a?(::Array) and color.size == 3)
|
@@ -341,7 +350,7 @@ module Origami
|
|
341
350
|
end
|
342
351
|
|
343
352
|
def set_stroke_color(color)
|
344
|
-
load!
|
353
|
+
load!
|
345
354
|
|
346
355
|
@instructions << ( i =
|
347
356
|
if (color.respond_to? :r and color.respond_to? :g and color.respond_to? :b) or (color.is_a?(::Array) and color.size == 3)
|
@@ -371,7 +380,8 @@ module Origami
|
|
371
380
|
end
|
372
381
|
|
373
382
|
def set_dash_pattern(pattern)
|
374
|
-
load!
|
383
|
+
load!
|
384
|
+
|
375
385
|
unless @canvas.gs.dash_pattern.eql? pattern
|
376
386
|
@instructions << PDF::Instruction.new('d', pattern.array, pattern.phase).render(@canvas)
|
377
387
|
end
|
@@ -380,7 +390,8 @@ module Origami
|
|
380
390
|
end
|
381
391
|
|
382
392
|
def set_line_width(width)
|
383
|
-
load!
|
393
|
+
load!
|
394
|
+
|
384
395
|
if @canvas.gs.line_width != width
|
385
396
|
@instructions << PDF::Instruction.new('w', width).render(@canvas)
|
386
397
|
end
|
@@ -389,7 +400,8 @@ module Origami
|
|
389
400
|
end
|
390
401
|
|
391
402
|
def set_line_cap(cap)
|
392
|
-
load!
|
403
|
+
load!
|
404
|
+
|
393
405
|
if @canvas.gs.line_cap != cap
|
394
406
|
@instructions << PDF::Instruction.new('J', cap).render(@canvas)
|
395
407
|
end
|
@@ -398,7 +410,8 @@ module Origami
|
|
398
410
|
end
|
399
411
|
|
400
412
|
def set_line_join(join)
|
401
|
-
load!
|
413
|
+
load!
|
414
|
+
|
402
415
|
if @canvas.gs.line_join != join
|
403
416
|
@instructions << PDF::Instruction.new('j', join).render(@canvas)
|
404
417
|
end
|
@@ -409,6 +422,8 @@ module Origami
|
|
409
422
|
private
|
410
423
|
|
411
424
|
def load!
|
425
|
+
return unless @instructions.nil?
|
426
|
+
|
412
427
|
decode!
|
413
428
|
|
414
429
|
code = StringScanner.new self.data
|
@@ -471,12 +486,12 @@ module Origami
|
|
471
486
|
end
|
472
487
|
|
473
488
|
# TODO :nodoc:
|
474
|
-
def paint_shading(
|
489
|
+
def paint_shading(_shade)
|
475
490
|
raise NotImplementedError
|
476
491
|
end
|
477
492
|
|
478
493
|
# TODO :nodoc:
|
479
|
-
def set_text_font(
|
494
|
+
def set_text_font(_font, _size)
|
480
495
|
raise NotImplementedError
|
481
496
|
end
|
482
497
|
|
@@ -607,7 +622,7 @@ module Origami
|
|
607
622
|
field :PtData, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3
|
608
623
|
|
609
624
|
def pre_build
|
610
|
-
self.Resources = Resources.new.pre_build unless
|
625
|
+
self.Resources = Resources.new.pre_build unless self.key?(:Resources)
|
611
626
|
|
612
627
|
super
|
613
628
|
end
|
@@ -645,7 +660,6 @@ module Origami
|
|
645
660
|
else
|
646
661
|
data = File.binread(File.expand_path(path))
|
647
662
|
format ||= File.extname(path)
|
648
|
-
format.slice!(0) if format and format[0,1] == '.'
|
649
663
|
end
|
650
664
|
|
651
665
|
image = ImageXObject.new
|
@@ -656,22 +670,18 @@ module Origami
|
|
656
670
|
image.setFilter :DCTDecode
|
657
671
|
image.encoded_data = data
|
658
672
|
|
659
|
-
image
|
660
|
-
|
661
673
|
when 'jp2','jpx','j2k','jpf','jpm','mj2'
|
662
674
|
image.setFilter :JPXDecode
|
663
675
|
image.encoded_data = data
|
664
676
|
|
665
|
-
image
|
666
|
-
|
667
677
|
when 'jb2', 'jbig', 'jbig2'
|
668
678
|
image.setFilter :JBIG2Decode
|
669
679
|
image.encoded_data = data
|
670
|
-
|
671
|
-
image
|
672
680
|
else
|
673
681
|
raise NotImplementedError, "Unknown file format: '#{format}'"
|
674
682
|
end
|
683
|
+
|
684
|
+
image
|
675
685
|
end
|
676
686
|
|
677
687
|
#
|
@@ -700,35 +710,35 @@ module Origami
|
|
700
710
|
|
701
711
|
case cs = self.ColorSpace.value
|
702
712
|
when Color::Space::DEVICE_GRAY
|
703
|
-
|
713
|
+
color_type = 0
|
704
714
|
components = 1
|
705
715
|
when Color::Space::DEVICE_RGB
|
706
|
-
|
716
|
+
color_type = 2
|
707
717
|
components = 3
|
708
718
|
when ::Array
|
709
|
-
|
710
|
-
case
|
719
|
+
cs_type = cs[0]
|
720
|
+
case cs_type
|
711
721
|
when :Indexed
|
712
|
-
|
722
|
+
color_type = 3
|
713
723
|
components = 3
|
714
|
-
|
715
|
-
lookup = cs[3]
|
724
|
+
cs_base = cs[1]
|
725
|
+
lookup = cs[3]
|
716
726
|
|
717
727
|
when :ICCBased
|
718
|
-
|
728
|
+
icc_profile = cs[1]
|
719
729
|
raise InvalidColorError,
|
720
|
-
"Invalid ICC Profile parameter" unless
|
730
|
+
"Invalid ICC Profile parameter" unless icc_profile.is_a?(Stream)
|
721
731
|
|
722
|
-
case
|
732
|
+
case icc_profile.N
|
723
733
|
when 1
|
724
|
-
|
734
|
+
color_type = 0
|
725
735
|
components = 1
|
726
736
|
when 3
|
727
|
-
|
737
|
+
color_type = 2
|
728
738
|
components = 3
|
729
739
|
else
|
730
740
|
raise InvalidColorError,
|
731
|
-
"Invalid number of components in ICC profile: #{
|
741
|
+
"Invalid number of components in ICC profile: #{icc_profile.N}"
|
732
742
|
end
|
733
743
|
else
|
734
744
|
raise InvalidColorError, "Unsupported color space: #{self.ColorSpace}"
|
@@ -738,7 +748,7 @@ module Origami
|
|
738
748
|
end
|
739
749
|
|
740
750
|
bpc = self.BitsPerComponent || 8
|
741
|
-
w,h = self.Width, self.Height
|
751
|
+
w, h = self.Width, self.Height
|
742
752
|
pixels = self.data
|
743
753
|
|
744
754
|
hdr = [137, 80, 78, 71, 13, 10, 26, 10].pack('C*')
|
@@ -749,7 +759,7 @@ module Origami
|
|
749
759
|
'IHDR',
|
750
760
|
[
|
751
761
|
w, h,
|
752
|
-
bpc,
|
762
|
+
bpc, color_type, 0, 0, 0
|
753
763
|
].pack("N2C5")
|
754
764
|
]
|
755
765
|
|
@@ -788,7 +798,7 @@ module Origami
|
|
788
798
|
]
|
789
799
|
end
|
790
800
|
|
791
|
-
if
|
801
|
+
if color_type == 3
|
792
802
|
lookup =
|
793
803
|
case lookup
|
794
804
|
when Stream then lookup.data
|
@@ -797,10 +807,10 @@ module Origami
|
|
797
807
|
raise InvalidColorError, "Invalid indexed palette table"
|
798
808
|
end
|
799
809
|
|
800
|
-
raise InvalidColorError, "Invalid base color space" unless
|
810
|
+
raise InvalidColorError, "Invalid base color space" unless cs_base
|
801
811
|
palette = ""
|
802
812
|
|
803
|
-
case
|
813
|
+
case cs_base
|
804
814
|
when Color::Space::DEVICE_GRAY
|
805
815
|
lookup.each_byte do |g|
|
806
816
|
palette << Color.gray_to_rgb(g).pack("C3")
|
@@ -815,13 +825,13 @@ module Origami
|
|
815
825
|
end
|
816
826
|
when ::Array
|
817
827
|
|
818
|
-
case
|
828
|
+
case cs_base[0]
|
819
829
|
when :ICCBased
|
820
|
-
|
830
|
+
icc_profile = cs_base[1]
|
821
831
|
raise InvalidColorError,
|
822
|
-
"Invalid ICC Profile parameter" unless
|
832
|
+
"Invalid ICC Profile parameter" unless icc_profile.is_a?(Stream)
|
823
833
|
|
824
|
-
case
|
834
|
+
case icc_profile.N
|
825
835
|
when 1
|
826
836
|
lookup.each_byte do |g|
|
827
837
|
palette << Color.gray_to_rgb(g).pack("C3")
|
@@ -830,20 +840,20 @@ module Origami
|
|
830
840
|
palette << lookup[0, (lookup.size / 3) * 3]
|
831
841
|
else
|
832
842
|
raise InvalidColorError,
|
833
|
-
"Invalid number of components in ICC profile: #{
|
843
|
+
"Invalid number of components in ICC profile: #{icc_profile.N}"
|
834
844
|
end
|
835
845
|
else
|
836
|
-
raise InvalidColorError, "Unsupported color space: #{
|
846
|
+
raise InvalidColorError, "Unsupported color space: #{cs_base}"
|
837
847
|
end
|
838
848
|
else
|
839
|
-
raise InvalidColorError, "Unsupported color space: #{
|
849
|
+
raise InvalidColorError, "Unsupported color space: #{cs_base}"
|
840
850
|
end
|
841
851
|
|
842
|
-
if
|
852
|
+
if icc_profile
|
843
853
|
chunks <<
|
844
854
|
[
|
845
855
|
'iCCP',
|
846
|
-
'ICC Profile' + "\x00\x00" + Zlib::Deflate.deflate(
|
856
|
+
'ICC Profile' + "\x00\x00" + Zlib::Deflate.deflate(icc_profile.data, Zlib::BEST_COMPRESSION)
|
847
857
|
]
|
848
858
|
end
|
849
859
|
|
@@ -855,12 +865,12 @@ module Origami
|
|
855
865
|
|
856
866
|
bpr = w
|
857
867
|
|
858
|
-
else #
|
859
|
-
if
|
868
|
+
else # color_type != 3
|
869
|
+
if icc_profile
|
860
870
|
chunks <<
|
861
871
|
[
|
862
872
|
'iCCP',
|
863
|
-
'ICC Profile' + "\x00\x00" + Zlib::Deflate.deflate(
|
873
|
+
'ICC Profile' + "\x00\x00" + Zlib::Deflate.deflate(icc_profile.data, Zlib::BEST_COMPRESSION)
|
864
874
|
]
|
865
875
|
end
|
866
876
|
|