origami 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING.LESSER +165 -0
- data/README +77 -0
- data/VERSION +1 -0
- data/bin/config/pdfcop.conf.yml +237 -0
- data/bin/gui/about.rb +46 -0
- data/bin/gui/config.rb +132 -0
- data/bin/gui/file.rb +385 -0
- data/bin/gui/hexdump.rb +74 -0
- data/bin/gui/hexview.rb +91 -0
- data/bin/gui/imgview.rb +72 -0
- data/bin/gui/menu.rb +392 -0
- data/bin/gui/properties.rb +132 -0
- data/bin/gui/signing.rb +635 -0
- data/bin/gui/textview.rb +107 -0
- data/bin/gui/treeview.rb +409 -0
- data/bin/gui/walker.rb +282 -0
- data/bin/gui/xrefs.rb +79 -0
- data/bin/pdf2graph +121 -0
- data/bin/pdf2ruby +353 -0
- data/bin/pdfcocoon +104 -0
- data/bin/pdfcop +455 -0
- data/bin/pdfdecompress +104 -0
- data/bin/pdfdecrypt +95 -0
- data/bin/pdfencrypt +112 -0
- data/bin/pdfextract +221 -0
- data/bin/pdfmetadata +123 -0
- data/bin/pdfsh +13 -0
- data/bin/pdfwalker +7 -0
- data/bin/shell/.irbrc +104 -0
- data/bin/shell/console.rb +136 -0
- data/bin/shell/hexdump.rb +83 -0
- data/origami.rb +36 -0
- data/origami/3d.rb +239 -0
- data/origami/acroform.rb +321 -0
- data/origami/actions.rb +299 -0
- data/origami/adobe/fdf.rb +259 -0
- data/origami/adobe/ppklite.rb +489 -0
- data/origami/annotations.rb +775 -0
- data/origami/array.rb +187 -0
- data/origami/boolean.rb +101 -0
- data/origami/catalog.rb +486 -0
- data/origami/destinations.rb +213 -0
- data/origami/dictionary.rb +188 -0
- data/origami/docmdp.rb +96 -0
- data/origami/encryption.rb +1293 -0
- data/origami/export.rb +283 -0
- data/origami/file.rb +222 -0
- data/origami/filters.rb +250 -0
- data/origami/filters/ascii.rb +189 -0
- data/origami/filters/ccitt.rb +515 -0
- data/origami/filters/crypt.rb +47 -0
- data/origami/filters/dct.rb +61 -0
- data/origami/filters/flate.rb +112 -0
- data/origami/filters/jbig2.rb +63 -0
- data/origami/filters/jpx.rb +53 -0
- data/origami/filters/lzw.rb +195 -0
- data/origami/filters/predictors.rb +276 -0
- data/origami/filters/runlength.rb +117 -0
- data/origami/font.rb +209 -0
- data/origami/functions.rb +93 -0
- data/origami/graphics.rb +33 -0
- data/origami/graphics/colors.rb +191 -0
- data/origami/graphics/instruction.rb +126 -0
- data/origami/graphics/path.rb +154 -0
- data/origami/graphics/patterns.rb +180 -0
- data/origami/graphics/state.rb +164 -0
- data/origami/graphics/text.rb +224 -0
- data/origami/graphics/xobject.rb +493 -0
- data/origami/header.rb +90 -0
- data/origami/linearization.rb +318 -0
- data/origami/metadata.rb +114 -0
- data/origami/name.rb +170 -0
- data/origami/null.rb +75 -0
- data/origami/numeric.rb +188 -0
- data/origami/obfuscation.rb +233 -0
- data/origami/object.rb +527 -0
- data/origami/outline.rb +59 -0
- data/origami/page.rb +559 -0
- data/origami/parser.rb +268 -0
- data/origami/parsers/fdf.rb +45 -0
- data/origami/parsers/pdf.rb +27 -0
- data/origami/parsers/pdf/linear.rb +113 -0
- data/origami/parsers/ppklite.rb +86 -0
- data/origami/pdf.rb +1144 -0
- data/origami/reference.rb +113 -0
- data/origami/signature.rb +474 -0
- data/origami/stream.rb +575 -0
- data/origami/string.rb +416 -0
- data/origami/trailer.rb +173 -0
- data/origami/webcapture.rb +87 -0
- data/origami/xfa.rb +3027 -0
- data/origami/xreftable.rb +447 -0
- data/templates/patterns.rb +66 -0
- data/templates/widgets.rb +173 -0
- data/templates/xdp.rb +92 -0
- data/tests/dataset/test.dummycrt +28 -0
- data/tests/dataset/test.dummykey +27 -0
- data/tests/tc_actions.rb +32 -0
- data/tests/tc_annotations.rb +85 -0
- data/tests/tc_pages.rb +37 -0
- data/tests/tc_pdfattach.rb +24 -0
- data/tests/tc_pdfencrypt.rb +110 -0
- data/tests/tc_pdfnew.rb +32 -0
- data/tests/tc_pdfparse.rb +98 -0
- data/tests/tc_pdfsig.rb +37 -0
- data/tests/tc_streams.rb +129 -0
- data/tests/ts_pdf.rb +45 -0
- metadata +193 -0
@@ -0,0 +1,493 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= File
|
4
|
+
graphics/xobject.rb
|
5
|
+
|
6
|
+
= Info
|
7
|
+
This file is part of Origami, PDF manipulation framework for Ruby
|
8
|
+
Copyright (C) 2010 Guillaume Delugré <guillaume@security-labs.org>
|
9
|
+
All right reserved.
|
10
|
+
|
11
|
+
Origami is free software: you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU Lesser General Public License as published by
|
13
|
+
the Free Software Foundation, either version 3 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
Origami is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU Lesser General Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU Lesser General Public License
|
22
|
+
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
23
|
+
|
24
|
+
=end
|
25
|
+
|
26
|
+
module Origami
|
27
|
+
|
28
|
+
#
|
29
|
+
# A class representing a Stream containing the contents of a Page.
|
30
|
+
#
|
31
|
+
class ContentStream < Stream
|
32
|
+
|
33
|
+
DEFAULT_SIZE = 12
|
34
|
+
DEFAULT_FONT = :F1
|
35
|
+
DEFAULT_LEADING = 20
|
36
|
+
DEFAULT_STROKE_COLOR = Graphics::Color::GrayScale.new(0.0)
|
37
|
+
DEFAULT_FILL_COLOR = Graphics::Color::GrayScale.new(1.0)
|
38
|
+
DEFAULT_LINECAP = Graphics::LineCapStyle::BUTT_CAP
|
39
|
+
DEFAULT_LINEJOIN = Graphics::LineJoinStyle::MITER_JOIN
|
40
|
+
DEFAULT_DASHPATTERN = Graphics::DashPattern.new([], 0)
|
41
|
+
DEFAULT_LINEWIDTH = 1.0
|
42
|
+
|
43
|
+
attr_reader :instructions
|
44
|
+
|
45
|
+
def initialize(rawdata = "", dictionary = {})
|
46
|
+
|
47
|
+
@instructions = nil
|
48
|
+
@gs = Graphics::State.new
|
49
|
+
|
50
|
+
super(rawdata, dictionary)
|
51
|
+
end
|
52
|
+
|
53
|
+
def pre_build #:nodoc:
|
54
|
+
load! if @instructions.nil?
|
55
|
+
if @gs.text_state.is_in_text_object?
|
56
|
+
@instructions << PDF::Instruction.new('ET').update_state(@gs)
|
57
|
+
end
|
58
|
+
|
59
|
+
@data = @instructions.join
|
60
|
+
|
61
|
+
super
|
62
|
+
end
|
63
|
+
|
64
|
+
def instructions
|
65
|
+
load! if @instructions.nil?
|
66
|
+
|
67
|
+
@instructions
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Draw a straight line from the point at coord _from_, to the point at coord _to_.
|
72
|
+
#
|
73
|
+
def draw_line(from, to, attr = {})
|
74
|
+
draw_polygon([from, to], attr)
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Draw a polygon from a array of coordinates.
|
79
|
+
#
|
80
|
+
def draw_polygon(coords = [], attr = {})
|
81
|
+
load! if @instructions.nil?
|
82
|
+
|
83
|
+
stroke_color = attr[:stroke_color] || DEFAULT_STROKE_COLOR
|
84
|
+
fill_color = attr[:fill_color] || DEFAULT_FILL_COLOR
|
85
|
+
line_cap = attr[:line_cap] || DEFAULT_LINECAP
|
86
|
+
line_join = attr[:line_join] || DEFAULT_LINEJOIN
|
87
|
+
line_width = attr[:line_width] || DEFAULT_LINEWIDTH
|
88
|
+
dash_pattern = attr[:dash] || DEFAULT_DASHPATTERN
|
89
|
+
|
90
|
+
stroke = attr[:stroke].nil? ? true : attr[:stroke]
|
91
|
+
fill = attr[:fill].nil? ? false : attr[:fill]
|
92
|
+
|
93
|
+
stroke = true if fill == false and stroke == false
|
94
|
+
|
95
|
+
set_fill_color(fill_color) if fill
|
96
|
+
set_stroke_color(stroke_color) if stroke
|
97
|
+
set_line_width(line_width)
|
98
|
+
set_line_cap(line_cap)
|
99
|
+
set_line_join(line_join)
|
100
|
+
set_dash_pattern(dash_pattern)
|
101
|
+
|
102
|
+
if @gs.text_state.is_in_text_object?
|
103
|
+
@instructions << PDF::Instruction.new('ET').update_state(@gs)
|
104
|
+
end
|
105
|
+
|
106
|
+
unless coords.size < 1
|
107
|
+
x,y = coords.slice!(0)
|
108
|
+
@instructions << PDF::Instruction.new('m',x,y).update_state(@gs)
|
109
|
+
|
110
|
+
coords.each do |px,py|
|
111
|
+
@instructions << PDF::Instruction.new('l',px,py).update_state(@gs)
|
112
|
+
end
|
113
|
+
|
114
|
+
@instructions << (i =
|
115
|
+
if stroke and not fill
|
116
|
+
PDF::Instruction.new('s')
|
117
|
+
elsif fill and not stroke
|
118
|
+
PDF::Instruction.new('f')
|
119
|
+
elsif fill and stroke
|
120
|
+
PDF::Instruction.new('b')
|
121
|
+
end
|
122
|
+
)
|
123
|
+
|
124
|
+
i.update_state(@gs)
|
125
|
+
end
|
126
|
+
|
127
|
+
self
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# Draw a rectangle at position (_x_,_y_) with defined _width_ and _height_.
|
132
|
+
#
|
133
|
+
def draw_rectangle(x, y, width, height, attr = {})
|
134
|
+
load! if @instructions.nil?
|
135
|
+
|
136
|
+
stroke_color = attr[:stroke_color] || DEFAULT_STROKE_COLOR
|
137
|
+
fill_color = attr[:fill_color] || DEFAULT_FILL_COLOR
|
138
|
+
line_cap = attr[:line_cap] || DEFAULT_LINECAP
|
139
|
+
line_join = attr[:line_join] || DEFAULT_LINEJOIN
|
140
|
+
line_width = attr[:line_width] || DEFAULT_LINEWIDTH
|
141
|
+
dash_pattern = attr[:dash] || DEFAULT_DASHPATTERN
|
142
|
+
|
143
|
+
stroke = attr[:stroke].nil? ? true : attr[:stroke]
|
144
|
+
fill = attr[:fill].nil? ? false : attr[:fill]
|
145
|
+
|
146
|
+
stroke = true if fill == false and stroke == false
|
147
|
+
|
148
|
+
set_fill_color(fill_color) if fill
|
149
|
+
set_stroke_color(stroke_color) if stroke
|
150
|
+
set_line_width(line_width)
|
151
|
+
set_line_cap(line_cap)
|
152
|
+
set_line_join(line_join)
|
153
|
+
set_dash_pattern(dash_pattern)
|
154
|
+
|
155
|
+
if @gs.text_state.is_in_text_object?
|
156
|
+
@instructions << PDF::Instruction.new('ET').update_state(@gs)
|
157
|
+
end
|
158
|
+
|
159
|
+
@instructions << PDF::Instruction.new('re', x,y,width,height).update_state(@gs)
|
160
|
+
|
161
|
+
@instructions << (i =
|
162
|
+
if stroke and not fill
|
163
|
+
PDF::Instruction.new('S')
|
164
|
+
elsif fill and not stroke
|
165
|
+
PDF::Instruction.new('f')
|
166
|
+
elsif fill and stroke
|
167
|
+
PDF::Instruction.new('B')
|
168
|
+
end
|
169
|
+
)
|
170
|
+
|
171
|
+
i.update_state(@gs)
|
172
|
+
|
173
|
+
self
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# Adds text to the content stream with custom formatting attributes.
|
178
|
+
# _text_:: Text to write.
|
179
|
+
# _attr_:: Formatting attributes.
|
180
|
+
#
|
181
|
+
def write(text, attr = {})
|
182
|
+
load! if @instructions.nil?
|
183
|
+
|
184
|
+
x,y = attr[:x], attr[:y]
|
185
|
+
font = attr[:font] || DEFAULT_FONT
|
186
|
+
size = attr[:size] || DEFAULT_SIZE
|
187
|
+
leading = attr[:leading] || DEFAULT_LEADING
|
188
|
+
color = attr[:color] || attr[:fill_color] || DEFAULT_STROKE_COLOR
|
189
|
+
stroke_color = attr[:stroke_color] || DEFAULT_STROKE_COLOR
|
190
|
+
line_width = attr[:line_width] || DEFAULT_LINEWIDTH
|
191
|
+
word_spacing = attr[:word_spacing]
|
192
|
+
char_spacing = attr[:char_spacing]
|
193
|
+
scale = attr[:scale]
|
194
|
+
rise = attr[:rise]
|
195
|
+
rendering = attr[:rendering]
|
196
|
+
|
197
|
+
@instructions << PDF::Instruction.new('ET').update_state(@gs) if (x or y) and @gs.text_state.is_in_text_object?
|
198
|
+
|
199
|
+
unless @gs.text_state.is_in_text_object?
|
200
|
+
@instructions << PDF::Instruction.new('BT').update_state(@gs)
|
201
|
+
end
|
202
|
+
|
203
|
+
set_text_font(font, size)
|
204
|
+
set_text_pos(x, y) if x or y
|
205
|
+
set_text_leading(leading) if leading
|
206
|
+
set_text_rendering(rendering) if rendering
|
207
|
+
set_text_rise(rise) if rise
|
208
|
+
set_text_scale(scale) if scale
|
209
|
+
set_text_word_spacing(word_spacing) if word_spacing
|
210
|
+
set_text_char_spacing(char_spacing) if char_spacing
|
211
|
+
set_fill_color(color)
|
212
|
+
set_stroke_color(stroke_color)
|
213
|
+
set_line_width(line_width)
|
214
|
+
|
215
|
+
write_text_block(text)
|
216
|
+
|
217
|
+
self
|
218
|
+
end
|
219
|
+
|
220
|
+
def paint_shading(shade)
|
221
|
+
load! if @instructions.nil?
|
222
|
+
@instructions << PDF::Instruction.new('sh', shade).update_state(@gs)
|
223
|
+
|
224
|
+
self
|
225
|
+
end
|
226
|
+
|
227
|
+
def set_text_font(fontname, size)
|
228
|
+
load! if @instructions.nil?
|
229
|
+
if fontname != @gs.text_state.font or size != @gs.text_state.font_size
|
230
|
+
@instructions << PDF::Instruction.new('Tf', fontname, size).update_state(@gs)
|
231
|
+
end
|
232
|
+
|
233
|
+
self
|
234
|
+
end
|
235
|
+
|
236
|
+
def set_text_pos(tx,ty)
|
237
|
+
load! if @instructions.nil?
|
238
|
+
@instructions << PDF::Instruction.new('Td', tx, ty).update_state(@gs)
|
239
|
+
|
240
|
+
self
|
241
|
+
end
|
242
|
+
|
243
|
+
def set_text_leading(leading)
|
244
|
+
load! if @instructions.nil?
|
245
|
+
if leading != @gs.text_state.leading
|
246
|
+
@instructions << PDF::Instruction.new('TL', leading).update_state(@gs)
|
247
|
+
end
|
248
|
+
|
249
|
+
self
|
250
|
+
end
|
251
|
+
|
252
|
+
def set_text_rendering(rendering)
|
253
|
+
load! if @instructions.nil?
|
254
|
+
if rendering != @gs.text_state.rendering_mode
|
255
|
+
@instructions << PDF::Instruction.new('Tr', rendering).update_state(@gs)
|
256
|
+
end
|
257
|
+
|
258
|
+
self
|
259
|
+
end
|
260
|
+
|
261
|
+
def set_text_rise(rise)
|
262
|
+
load! if @instructions.nil?
|
263
|
+
if rise != @gs.text_state.text_rise
|
264
|
+
@instructions << PDF::Instruction.new('Ts', rise).update_state(@gs)
|
265
|
+
end
|
266
|
+
|
267
|
+
self
|
268
|
+
end
|
269
|
+
|
270
|
+
def set_text_scale(scaling)
|
271
|
+
load! if @instructions.nil?
|
272
|
+
if scale != @gs.text_state.scaling
|
273
|
+
@instructions << PDF::Instruction.new('Tz', scaling).update_state(@gs)
|
274
|
+
end
|
275
|
+
|
276
|
+
self
|
277
|
+
end
|
278
|
+
|
279
|
+
def set_text_word_spacing(word_spacing)
|
280
|
+
load! if @instructions.nil?
|
281
|
+
if word_spacing != @gs.text_state.word_spacing
|
282
|
+
@instructions << PDF::Instruction.new('Tw', word_spacing).update_state(@gs)
|
283
|
+
end
|
284
|
+
|
285
|
+
self
|
286
|
+
end
|
287
|
+
|
288
|
+
def set_text_char_spacing(char_spacing)
|
289
|
+
load! if @instructions.nil?
|
290
|
+
if char_spacing != @gs.text_state.char_spacing
|
291
|
+
@instructions << PDF::Instruction.new('Tc', char_spacing).update_state(@gs)
|
292
|
+
end
|
293
|
+
|
294
|
+
self
|
295
|
+
end
|
296
|
+
|
297
|
+
def set_fill_color(color)
|
298
|
+
load! if @instructions.nil?
|
299
|
+
|
300
|
+
@instructions << ( i =
|
301
|
+
if (color.respond_to? :r and color.respond_to? :g and color.respond_to? :b) or (color.is_a?(::Array) and color.size == 3)
|
302
|
+
r = (color.respond_to?(:r) ? color.r : color[0]).to_f / 255
|
303
|
+
g = (color.respond_to?(:g) ? color.g : color[1]).to_f / 255
|
304
|
+
b = (color.respond_to?(:b) ? color.b : color[2]).to_f / 255
|
305
|
+
PDF::Instruction.new('rg', r, g, b) if @gs.nonstroking_color != [r,g,b]
|
306
|
+
|
307
|
+
elsif (color.respond_to? :c and color.respond_to? :m and color.respond_to? :y and color.respond_to? :k) or (color.is_a?(::Array) and color.size == 4)
|
308
|
+
c = (color.respond_to?(:c) ? color.c : color[0]).to_f
|
309
|
+
m = (color.respond_to?(:m) ? color.m : color[1]).to_f
|
310
|
+
y = (color.respond_to?(:y) ? color.y : color[2]).to_f
|
311
|
+
k = (color.respond_to?(:k) ? color.k : color[3]).to_f
|
312
|
+
PDF::Instruction.new('k', c, m, y, k) if @gs.nonstroking_color != [c,m,y,k]
|
313
|
+
|
314
|
+
elsif color.respond_to?:g or (0.0..1.0) === color
|
315
|
+
g = color.respond_to?(:g) ? color.g : color
|
316
|
+
PDF::Instruction.new('g', g) if @gs.nonstroking_color != [ g ]
|
317
|
+
|
318
|
+
else
|
319
|
+
raise TypeError, "Invalid color : #{color}"
|
320
|
+
end
|
321
|
+
)
|
322
|
+
|
323
|
+
i.update_state(@gs) if i
|
324
|
+
self
|
325
|
+
end
|
326
|
+
|
327
|
+
def set_stroke_color(color)
|
328
|
+
load! if @instructions.nil?
|
329
|
+
|
330
|
+
@instructions << ( i =
|
331
|
+
if (color.respond_to? :r and color.respond_to? :g and color.respond_to? :b) or (color.is_a?(::Array) and color.size == 3)
|
332
|
+
r = (color.respond_to?(:r) ? color.r : color[0]).to_f / 255
|
333
|
+
g = (color.respond_to?(:g) ? color.g : color[1]).to_f / 255
|
334
|
+
b = (color.respond_to?(:b) ? color.b : color[2]).to_f / 255
|
335
|
+
PDF::Instruction.new('RG', r, g, b) if @gs.stroking_color != [r,g,b]
|
336
|
+
|
337
|
+
elsif (color.respond_to? :c and color.respond_to? :m and color.respond_to? :y and color.respond_to? :k) or (color.is_a?(::Array) and color.size == 4)
|
338
|
+
c = (color.respond_to?(:c) ? color.c : color[0]).to_f
|
339
|
+
m = (color.respond_to?(:m) ? color.m : color[1]).to_f
|
340
|
+
y = (color.respond_to?(:y) ? color.y : color[2]).to_f
|
341
|
+
k = (color.respond_to?(:k) ? color.k : color[3]).to_f
|
342
|
+
PDF::Instruction.new('K', c, m, y, k) if @gs.stroking_color != [c,m,y,k]
|
343
|
+
|
344
|
+
elsif color.respond_to?:g or (0.0..1.0) === color
|
345
|
+
g = color.respond_to?(:g) ? color.g : color
|
346
|
+
PDF::Instruction.new('G', g) if @gs.stroking_color != [ g ]
|
347
|
+
|
348
|
+
else
|
349
|
+
raise TypeError, "Invalid color : #{color}"
|
350
|
+
end
|
351
|
+
)
|
352
|
+
|
353
|
+
i.update_state(@gs) if i
|
354
|
+
self
|
355
|
+
end
|
356
|
+
|
357
|
+
def set_dash_pattern(pattern)
|
358
|
+
load! if @instructions.nil?
|
359
|
+
unless @gs.dash_pattern.eql? pattern
|
360
|
+
@instructions << PDF::Instruction.new('d', pattern.array, pattern.phase).update_state(@gs)
|
361
|
+
end
|
362
|
+
|
363
|
+
self
|
364
|
+
end
|
365
|
+
|
366
|
+
def set_line_width(width)
|
367
|
+
load! if @instructions.nil?
|
368
|
+
if @gs.line_width != width
|
369
|
+
@instructions << PDF::Instruction.new('w', width).update_state(@gs)
|
370
|
+
end
|
371
|
+
|
372
|
+
self
|
373
|
+
end
|
374
|
+
|
375
|
+
def set_line_cap(cap)
|
376
|
+
load! if @instructions.nil?
|
377
|
+
if @gs.line_cap != cap
|
378
|
+
@instructions << PDF::Instruction.new('J', cap).update_state(@gs)
|
379
|
+
end
|
380
|
+
|
381
|
+
self
|
382
|
+
end
|
383
|
+
|
384
|
+
def set_line_join(join)
|
385
|
+
load! if @instructions.nil?
|
386
|
+
if @gs.line_join != join
|
387
|
+
@instructions << PDF::Instruction.new('j', join).update_state(@gs)
|
388
|
+
end
|
389
|
+
|
390
|
+
self
|
391
|
+
end
|
392
|
+
|
393
|
+
private
|
394
|
+
|
395
|
+
def load!
|
396
|
+
decode!
|
397
|
+
|
398
|
+
code = StringScanner.new self.data
|
399
|
+
@instructions = []
|
400
|
+
@instructions << PDF::Instruction.parse(code) until code.eos?
|
401
|
+
|
402
|
+
self
|
403
|
+
end
|
404
|
+
|
405
|
+
def write_text_block(text)
|
406
|
+
|
407
|
+
lines = text.split("\n").map!{|line| line.to_s}
|
408
|
+
|
409
|
+
@instructions << PDF::Instruction.new('Tj', lines.slice!(0)).update_state(@gs)
|
410
|
+
lines.each do |line|
|
411
|
+
@instructions << PDF::Instruction.new("'", line).update_state(@gs)
|
412
|
+
end
|
413
|
+
|
414
|
+
end
|
415
|
+
|
416
|
+
end #class ContentStream
|
417
|
+
|
418
|
+
module Graphics
|
419
|
+
|
420
|
+
module XObject
|
421
|
+
def self.included(receiver)
|
422
|
+
receiver.field :Type, :Type => Name, :Default => :XObject
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
class FormXObject < ContentStream
|
427
|
+
include XObject
|
428
|
+
|
429
|
+
field :Subtype, :Type => Name, :Default => :Form, :Required => true
|
430
|
+
field :FormType, :Type => Integer, :Default => 1
|
431
|
+
field :BBox, :Type => Array, :Required => true
|
432
|
+
field :Matrix, :Type => Array, :Default => [1, 0, 0, 1, 0, 0]
|
433
|
+
field :Resources, :Type => Dictionary, :Version => "1.2"
|
434
|
+
field :Group, :Type => Dictionary, :Version => "1.4"
|
435
|
+
field :Ref, :Type => Dictionary, :Version => "1.4"
|
436
|
+
field :Metadata, :Type => Stream, :Version => "1.4"
|
437
|
+
field :PieceInfo, :Type => Dictionary, :Version => "1.3"
|
438
|
+
field :LastModified, :Type => String, :Version => "1.3"
|
439
|
+
field :StructParent, :Type => Integer, :Version => "1.3"
|
440
|
+
field :StructParents, :Type => Integer, :Version => "1.3"
|
441
|
+
field :OPI, :Type => Dictionary, :Version => "1.2"
|
442
|
+
field :OC, :Type => Dictionary, :Version => "1.5"
|
443
|
+
field :Name, :Type => Name
|
444
|
+
field :Measure, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3
|
445
|
+
field :PtData, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3
|
446
|
+
|
447
|
+
def pre_build
|
448
|
+
self.Resources = Resources.new.pre_build unless has_field?(:Resources)
|
449
|
+
|
450
|
+
super
|
451
|
+
end
|
452
|
+
|
453
|
+
end
|
454
|
+
|
455
|
+
class ImageXObject < Stream
|
456
|
+
include XObject
|
457
|
+
|
458
|
+
field :Subtype, :Type => Name, :Default => :Image, :Required => true
|
459
|
+
field :Width, :Type => Integer, :Required => true
|
460
|
+
field :Height, :Type => Integer, :Required => true
|
461
|
+
field :ColorSpace, :Type => [ Name, Array ]
|
462
|
+
field :BitsPerComponent, :Type => Integer
|
463
|
+
field :Intent, :Type => Name, :Version => "1.1"
|
464
|
+
field :ImageMask, :Type => Boolean, :Default => false
|
465
|
+
field :Mask, :Type => [ Stream, Array ], :Version => "1.3"
|
466
|
+
field :Decode, :Type => Array
|
467
|
+
field :Interpolate, :Type => Boolean, :Default => false
|
468
|
+
field :Alternates, :Type => Array, :Version => "1.3"
|
469
|
+
field :SMask, :Type => Stream, :Version => "1.4"
|
470
|
+
field :SMaskInData, :Type => Integer, :Default => 0, :Version => "1.5"
|
471
|
+
field :Name, :Type => Name
|
472
|
+
field :StructParent, :Type => Integer, :Version => "1.3"
|
473
|
+
field :ID, :Type => String, :Version => "1.3"
|
474
|
+
field :OPI, :Type => Dictionary, :Version => "1.2"
|
475
|
+
field :Metadata, :Type => Stream, :Version => "1.4"
|
476
|
+
field :OC, :Type => Dictionary, :Version => "1.5"
|
477
|
+
field :Measure, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3
|
478
|
+
field :PtData, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3
|
479
|
+
|
480
|
+
end
|
481
|
+
|
482
|
+
class ReferenceDictionary < Dictionary
|
483
|
+
include StandardObject
|
484
|
+
|
485
|
+
field :F, :Type => Dictionary, :Required => true
|
486
|
+
field :Page, :Type => [Integer, String], :Required => true
|
487
|
+
field :ID, :Tyoe => Array
|
488
|
+
end
|
489
|
+
|
490
|
+
end
|
491
|
+
|
492
|
+
end
|
493
|
+
|