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