eventioz-pdf-writer 1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/ChangeLog +113 -0
- data/Demo-README +43 -0
- data/Gemfile +4 -0
- data/LICENCE +131 -0
- data/README +33 -0
- data/Rakefile +1 -0
- data/Release-Announcement +87 -0
- data/bin/techbook +24 -0
- data/bugs/first_page_margins.rb +28 -0
- data/bugs/page_numbering_simple.rb +14 -0
- data/bugs/page_numbering_stop_and_start.rb +21 -0
- data/demo/chunkybacon.rb +36 -0
- data/demo/code.rb +71 -0
- data/demo/colornames.rb +47 -0
- data/demo/demo.rb +73 -0
- data/demo/gettysburg.rb +66 -0
- data/demo/hello.rb +26 -0
- data/demo/individual-i.rb +89 -0
- data/demo/pac.rb +70 -0
- data/demo/qr-language.rb +580 -0
- data/demo/qr-library.rb +380 -0
- data/images/bluesmoke.jpg +0 -0
- data/images/chunkybacon.jpg +0 -0
- data/images/chunkybacon.png +0 -0
- data/lib/pdf/charts.rb +13 -0
- data/lib/pdf/charts/stddev.rb +431 -0
- data/lib/pdf/core_ext/mutex.rb +11 -0
- data/lib/pdf/math.rb +108 -0
- data/lib/pdf/quickref.rb +333 -0
- data/lib/pdf/simpletable.rb +948 -0
- data/lib/pdf/techbook.rb +905 -0
- data/lib/pdf/writer.rb +2734 -0
- data/lib/pdf/writer/arc4.rb +63 -0
- data/lib/pdf/writer/fontmetrics.rb +203 -0
- data/lib/pdf/writer/fonts/Courier-Bold.afm +342 -0
- data/lib/pdf/writer/fonts/Courier-BoldOblique.afm +342 -0
- data/lib/pdf/writer/fonts/Courier-Oblique.afm +342 -0
- data/lib/pdf/writer/fonts/Courier.afm +342 -0
- data/lib/pdf/writer/fonts/Helvetica-Bold.afm +2827 -0
- data/lib/pdf/writer/fonts/Helvetica-BoldOblique.afm +2827 -0
- data/lib/pdf/writer/fonts/Helvetica-Oblique.afm +3051 -0
- data/lib/pdf/writer/fonts/Helvetica.afm +3051 -0
- data/lib/pdf/writer/fonts/MustRead.html +19 -0
- data/lib/pdf/writer/fonts/Symbol.afm +213 -0
- data/lib/pdf/writer/fonts/Times-Bold.afm +2588 -0
- data/lib/pdf/writer/fonts/Times-BoldItalic.afm +2384 -0
- data/lib/pdf/writer/fonts/Times-Italic.afm +2667 -0
- data/lib/pdf/writer/fonts/Times-Roman.afm +2419 -0
- data/lib/pdf/writer/fonts/ZapfDingbats.afm +225 -0
- data/lib/pdf/writer/graphics.rb +817 -0
- data/lib/pdf/writer/graphics/imageinfo.rb +365 -0
- data/lib/pdf/writer/lang.rb +43 -0
- data/lib/pdf/writer/lang/en.rb +99 -0
- data/lib/pdf/writer/object.rb +23 -0
- data/lib/pdf/writer/object/action.rb +35 -0
- data/lib/pdf/writer/object/annotation.rb +42 -0
- data/lib/pdf/writer/object/catalog.rb +39 -0
- data/lib/pdf/writer/object/contents.rb +70 -0
- data/lib/pdf/writer/object/destination.rb +40 -0
- data/lib/pdf/writer/object/encryption.rb +53 -0
- data/lib/pdf/writer/object/font.rb +72 -0
- data/lib/pdf/writer/object/fontdescriptor.rb +34 -0
- data/lib/pdf/writer/object/fontencoding.rb +40 -0
- data/lib/pdf/writer/object/image.rb +304 -0
- data/lib/pdf/writer/object/info.rb +51 -0
- data/lib/pdf/writer/object/outline.rb +30 -0
- data/lib/pdf/writer/object/outlines.rb +30 -0
- data/lib/pdf/writer/object/page.rb +195 -0
- data/lib/pdf/writer/object/pages.rb +115 -0
- data/lib/pdf/writer/object/procset.rb +46 -0
- data/lib/pdf/writer/object/viewerpreferences.rb +74 -0
- data/lib/pdf/writer/ohash.rb +58 -0
- data/lib/pdf/writer/oreader.rb +25 -0
- data/lib/pdf/writer/state.rb +48 -0
- data/lib/pdf/writer/strokestyle.rb +138 -0
- data/manual.pwd +5965 -0
- data/metaconfig +13 -0
- data/pdf-writer.gemspec +28 -0
- data/pre-setup.rb +56 -0
- data/setup.rb +1366 -0
- data/test/helper.rb +4 -0
- data/test/test_image_info.rb +16 -0
- data/test/test_page_numbering.rb +13 -0
- metadata +196 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# PDF::Writer for Ruby.
|
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
|
7
|
+
# for full licensing information.
|
|
8
|
+
#
|
|
9
|
+
# $Id$
|
|
10
|
+
#++
|
|
11
|
+
require 'pdf/writer/oreader'
|
|
12
|
+
|
|
13
|
+
# An image object. This will be an /XObject dictionary in the document. This
|
|
14
|
+
# includes description and data. The diectionary includes:
|
|
15
|
+
#
|
|
16
|
+
# Type:: (name, Optional) The type of PDF object that this
|
|
17
|
+
# dictionary describes; if present, must be /XObject for
|
|
18
|
+
# an image XObject.
|
|
19
|
+
# Subtype:: (name, Required) The type of XObject that this
|
|
20
|
+
# dictionary describes; must be /Image for an image
|
|
21
|
+
# /XObject.
|
|
22
|
+
# Width:: (integer, Required) The width of the image, in samples.
|
|
23
|
+
# Height:: (integer, Required) The height of the image, in samples.
|
|
24
|
+
# ColorSpace:: (name or array, Required for images, except those that
|
|
25
|
+
# use the /JPXDecode filter; not allowed for image
|
|
26
|
+
# masks) The color space in which image samples are
|
|
27
|
+
# specified; it can be any type of color space except
|
|
28
|
+
# /Pattern. If the image uses the JPXDecode filter, this
|
|
29
|
+
# entry is optional: * If /ColorSpace is present, any
|
|
30
|
+
# color space specifications in the JPEG2000 data are
|
|
31
|
+
# ignored. * If /ColorSpace is absent, the color space
|
|
32
|
+
# specifications in the JPEG2000 data are used. The
|
|
33
|
+
# /Decode array is also ignored unless /ImageMask is
|
|
34
|
+
# true.
|
|
35
|
+
# BitsPerComponent:: (integer, Required except for image masks and images
|
|
36
|
+
# that use the JPXDecode filter) The number of bits used
|
|
37
|
+
# to represent each color component. Only a single value
|
|
38
|
+
# may be specified; the number of bits is the same for
|
|
39
|
+
# all color components. Valid values are 1, 2, 4, 8, and
|
|
40
|
+
# (in PDF 1.5) 16. If /ImageMask is true, this entry is
|
|
41
|
+
# optional, and if specified, its value must be 1. If
|
|
42
|
+
# the image stream uses a filter, the value of
|
|
43
|
+
# BitsPerComponent must be consistent with the size of
|
|
44
|
+
# the data samples that the filter delivers. In
|
|
45
|
+
# particular, a CCITTFaxDecode or JBIG2Decode filter
|
|
46
|
+
# always delivers 1-bit samples, a RunLengthDecode or
|
|
47
|
+
# DCTDecode filter delivers 8-bit samples, and an
|
|
48
|
+
# LZWDecode or FlateDecode filter delivers samples of a
|
|
49
|
+
# specified size if a predictor function is used. If the
|
|
50
|
+
# image stream uses the JPXDecode filter, this entry is
|
|
51
|
+
# optional and ignored if present. The bit depth is
|
|
52
|
+
# determined in the process of decoding the JPEG2000
|
|
53
|
+
# image.
|
|
54
|
+
# Intent:: (name, Optional; PDF 1.1) The name of a color
|
|
55
|
+
# rendering intent to be used in rendering the image
|
|
56
|
+
# (see �Rendering Intents� on page 230). Default value:
|
|
57
|
+
# the current rendering intent in the graphics state.
|
|
58
|
+
# ImageMask:: (boolean, Optional) A flag indicating whether the
|
|
59
|
+
# image is to be treated as an image mask (see Section
|
|
60
|
+
# 4.8.5, �Masked Images�). If this flag is true, the
|
|
61
|
+
# value of /BitsPerComponent must be 1 and Mask and
|
|
62
|
+
# /ColorSpace should not be specified; unmasked areas
|
|
63
|
+
# are painted using the current nonstroking color.
|
|
64
|
+
# Default value: false.
|
|
65
|
+
# Mask:: (stream or array, Optional except for image masks; not
|
|
66
|
+
# allowed for image masks; PDF 1.3) An image XObject
|
|
67
|
+
# defining an image mask to be applied to this image
|
|
68
|
+
# (see �Explicit Masking� on page 321), or an array
|
|
69
|
+
# specifying a range of colors to be applied to it as a
|
|
70
|
+
# color key mask (see �Color Key Masking� on page 321).
|
|
71
|
+
# If ImageMask is true, this entry must not be present.
|
|
72
|
+
# (See implementation note 51 in Appendix H.)
|
|
73
|
+
# Decode:: (array, Optional) An array of numbers describing how
|
|
74
|
+
# to map image samples into the range of values
|
|
75
|
+
# appropriate for the image�s color space (see �Decode
|
|
76
|
+
# Arrays� on page 314). If ImageMask is true, the array
|
|
77
|
+
# must be either [0 1] or [1 0]; otherwise, its length
|
|
78
|
+
# must be twice the number of color components required
|
|
79
|
+
# by ColorSpace. If the image uses the JPXDecode filter
|
|
80
|
+
# and ImageMask is false, Decode is ignored. Default
|
|
81
|
+
# value: see �Decode Arrays� on page 314.
|
|
82
|
+
# Interpolate:: (boolean, Optional) A flag indicating whether image
|
|
83
|
+
# interpolation is to be performed (see �Image
|
|
84
|
+
# Interpolation� on page 316). Default value: false.
|
|
85
|
+
# Alternates:: (array, Optional; PDF 1.3) An array of alternate image
|
|
86
|
+
# dictionaries for this image (see �Alternate Images� on
|
|
87
|
+
# page 317). The order of elements within the array has
|
|
88
|
+
# no significance. This entry may not be present in an
|
|
89
|
+
# image XObject that is itself an alternate image.
|
|
90
|
+
# SMask:: (stream, Optional; PDF 1.4) A subsidiary image XObject
|
|
91
|
+
# defining a soft-mask image (see �Soft-Mask Images� on
|
|
92
|
+
# page 522) to be used as a source of mask shape or mask
|
|
93
|
+
# opacity values in the transparent imaging model. The
|
|
94
|
+
# alpha source parameter in the graphics state
|
|
95
|
+
# determines whether the mask values are interpreted as
|
|
96
|
+
# shape or opacity. If present, this entry overrides the
|
|
97
|
+
# current soft mask in the graphics state, as well as
|
|
98
|
+
# the image�s Mask entry, if any. (However, the other
|
|
99
|
+
# transparency related graphics state parameters�blend
|
|
100
|
+
# mode and alpha constant�remain in effect.) If SMask is
|
|
101
|
+
# absent, the image has no associated soft mask
|
|
102
|
+
# (although the current soft mask in the graphics state
|
|
103
|
+
# may still apply).
|
|
104
|
+
# SMaskInData:: (integer, Optional for images that use the JPXDecode
|
|
105
|
+
# filter, meaningless otherwise; PDF 1.5) A code
|
|
106
|
+
# specifying how soft-mask information (see �Soft-Mask
|
|
107
|
+
# Images� on page 522) encoded with image samples should
|
|
108
|
+
# be used: (0) If present, encoded soft-mask image
|
|
109
|
+
# information should be ignored. (1) The image�s data
|
|
110
|
+
# stream includes encoded soft-mask values. An
|
|
111
|
+
# application can create a soft-mask image from the
|
|
112
|
+
# information to be used as a source of mask shape or
|
|
113
|
+
# mask opacity in the transparency imaging model. (2)
|
|
114
|
+
# The image�s data stream includes color channels that
|
|
115
|
+
# have been preblended with a background; the image data
|
|
116
|
+
# also includes an opacity channel. An application can
|
|
117
|
+
# create a soft-mask image with a Matte entry from the
|
|
118
|
+
# opacity channel information to be used as a source of
|
|
119
|
+
# mask shape or mask opacity in the transparency model.
|
|
120
|
+
# * If this entry has a nonzero value, SMask should not
|
|
121
|
+
# be specified. See also Section 3.3.8, �JPXDecode
|
|
122
|
+
# Filter.� Default value: 0.
|
|
123
|
+
# Name:: (name, Required in PDF 1.0; optional otherwise) The
|
|
124
|
+
# name by which this image XObject is referenced in the
|
|
125
|
+
# XObject subdictionary of the current resource
|
|
126
|
+
# dictionary (see Section 3.7.2, �Resource
|
|
127
|
+
# Dictionaries�). Note: This entry is obsolescent and
|
|
128
|
+
# its use is no longer recommended. (See implementation
|
|
129
|
+
# note 52 in Appendix H.)
|
|
130
|
+
# StructParent:: (integer, Required if the image is a structural
|
|
131
|
+
# content item; PDF 1.3) The integer key of the image�s
|
|
132
|
+
# entry in the structural parent tree (see �Finding
|
|
133
|
+
# Structure Elements from Content Items� on page 797).
|
|
134
|
+
# ID:: (string, Optional; PDF 1.3; indirect reference
|
|
135
|
+
# preferred) The digital identifier of the image�s
|
|
136
|
+
# parent Web Capture content set (see Section 10.9.5,
|
|
137
|
+
# �Object Attributes Related to Web Capture�).
|
|
138
|
+
# OPI:: (dictionary, Optional; PDF 1.2) An OPI version
|
|
139
|
+
# dictionary for the image (see Section 10.10.6, �Open
|
|
140
|
+
# Prepress Interface (OPI)�). If ImageMask is true, this
|
|
141
|
+
# entry is ignored.
|
|
142
|
+
# Metadata:: (stream, Optional; PDF 1.4) A metadata stream
|
|
143
|
+
# containing metadata for the image (see Section 10.2.2,
|
|
144
|
+
# �Metadata Streams�).
|
|
145
|
+
# OC:: (dictionary, Optional; PDF 1.5) An optional content
|
|
146
|
+
# group or optional content membership dictionary (see
|
|
147
|
+
# Section 4.10, �Optional Content�), specifying the
|
|
148
|
+
# optional content properties for this image XObject.
|
|
149
|
+
# Before the image is processed, its visibility is
|
|
150
|
+
# determined based on this entry. If it is determined to
|
|
151
|
+
# be invisible, the entire image is skipped, as if there
|
|
152
|
+
# were no Do operator to invoke it.
|
|
153
|
+
class PDF::Writer::External::Image < PDF::Writer::External
|
|
154
|
+
attr_reader :label
|
|
155
|
+
attr_reader :image_info
|
|
156
|
+
|
|
157
|
+
def initialize(parent, data, image, label)
|
|
158
|
+
super(parent)
|
|
159
|
+
|
|
160
|
+
@data = data
|
|
161
|
+
|
|
162
|
+
@image_info = image
|
|
163
|
+
|
|
164
|
+
@info = {
|
|
165
|
+
'Type' => '/XObject',
|
|
166
|
+
'Subtype' => '/Image',
|
|
167
|
+
'Width' => image.width,
|
|
168
|
+
'Height' => image.height
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
case image.format
|
|
172
|
+
when "JPEG"
|
|
173
|
+
case image.channels
|
|
174
|
+
when 1
|
|
175
|
+
@info['ColorSpace'] = '/DeviceGray'
|
|
176
|
+
when 4
|
|
177
|
+
@info['ColorSpace'] = '/DeviceCMYK'
|
|
178
|
+
# This should fix problems with CMYK JPEG colours inverted in
|
|
179
|
+
# Adobe Acrobat. Enable only if appropriate.
|
|
180
|
+
# @info['Decode'] = '[1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0]'
|
|
181
|
+
else
|
|
182
|
+
@info['ColorSpace'] = '/DeviceRGB'
|
|
183
|
+
end
|
|
184
|
+
@info['Filter'] = '/DCTDecode'
|
|
185
|
+
@info['BitsPerComponent'] = 8
|
|
186
|
+
when "PNG"
|
|
187
|
+
if image.info[:compression_method] != 0
|
|
188
|
+
raise TypeError, PDF::Writer::Lang[:png_unsupp_compres]
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
if image.info[:filter_method] != 0
|
|
192
|
+
raise TypeError, PDF::Writer::Lang[:png_unsupp_filter]
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
data = data.dup
|
|
196
|
+
data.extend(PDF::Writer::OffsetReader)
|
|
197
|
+
|
|
198
|
+
data.read_o(8) # Skip the default header
|
|
199
|
+
|
|
200
|
+
ok = true
|
|
201
|
+
length = data.size
|
|
202
|
+
palette = ""
|
|
203
|
+
idat = ""
|
|
204
|
+
|
|
205
|
+
while ok
|
|
206
|
+
chunk_size = data.read_o(4).unpack("N")[0]
|
|
207
|
+
section = data.read_o(4)
|
|
208
|
+
case section
|
|
209
|
+
when 'PLTE'
|
|
210
|
+
palette << data.read_o(chunk_size)
|
|
211
|
+
when 'IDAT'
|
|
212
|
+
idat << data.read_o(chunk_size)
|
|
213
|
+
when 'tRNS'
|
|
214
|
+
# This chunk can only occur once and it must occur after the
|
|
215
|
+
# PLTE chunk and before the IDAT chunk
|
|
216
|
+
trans = {}
|
|
217
|
+
case image.info[:color_type]
|
|
218
|
+
when 3
|
|
219
|
+
# Indexed colour, RGB. Each byte in this chunk is an alpha for
|
|
220
|
+
# the palette index in the PLTE ("palette") chunk up until the
|
|
221
|
+
# last non-opaque entry. Set up an array, stretching over all
|
|
222
|
+
# palette entries which will be 0 (opaque) or 1 (transparent).
|
|
223
|
+
trans[:type] = 'indexed'
|
|
224
|
+
trans[:data] = data.read_o(chunk_size).unpack("C*")
|
|
225
|
+
when 0
|
|
226
|
+
# Greyscale. Corresponding to entries in the PLTE chunk.
|
|
227
|
+
# Grey is two bytes, range 0 .. (2 ^ bit-depth) - 1
|
|
228
|
+
trans[:grayscale] = data.read_o(2).unpack("n")
|
|
229
|
+
trans[:type] = 'indexed'
|
|
230
|
+
# trans[:data] = data.read_o.unpack("C")
|
|
231
|
+
when 2
|
|
232
|
+
# True colour with proper alpha channel.
|
|
233
|
+
trans[:rgb] = data.read_o(6).unpack("nnn")
|
|
234
|
+
end
|
|
235
|
+
else
|
|
236
|
+
data.offset += chunk_size
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
ok = (section != "IEND")
|
|
240
|
+
|
|
241
|
+
data.read_o(4) # Skip the CRC
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
if image.bits > 8
|
|
245
|
+
raise TypeError, PDF::Writer::Lang[:png_8bit_colour]
|
|
246
|
+
end
|
|
247
|
+
if image.info[:interlace_method] != 0
|
|
248
|
+
raise TypeError, PDF::Writer::Lang[:png_interlace]
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
ncolor = 1
|
|
252
|
+
colour = 'DeviceRGB'
|
|
253
|
+
case image.info[:color_type]
|
|
254
|
+
when 3
|
|
255
|
+
nil
|
|
256
|
+
when 2
|
|
257
|
+
ncolor = 3
|
|
258
|
+
when 0
|
|
259
|
+
colour = 'DeviceGray'
|
|
260
|
+
else
|
|
261
|
+
raise TypeError, PDF::Writer::Lang[:png_alpha_trans]
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
@info['Filter'] = '[/FlateDecode]'
|
|
265
|
+
@info['DecodeParms'] = "[<</Predictor 15 /Colors #{ncolor} /Columns #{image.width}>>]"
|
|
266
|
+
@info['BitsPerComponent'] = image.bits.to_s
|
|
267
|
+
|
|
268
|
+
unless palette.empty?
|
|
269
|
+
@info['ColorSpace'] = " [ /Indexed /DeviceRGB #{(palette.size / 3) - 1} "
|
|
270
|
+
contents = PDF::Writer::Object::Contents.new(parent,
|
|
271
|
+
self)
|
|
272
|
+
contents.data = palette
|
|
273
|
+
@info['ColorSpace'] << "#{contents.oid} 0 R ]"
|
|
274
|
+
|
|
275
|
+
if trans
|
|
276
|
+
case trans[:type]
|
|
277
|
+
when 'indexed'
|
|
278
|
+
@info['Mask'] = " [ #{trans[:data].join(' ')} ] "
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
else
|
|
282
|
+
@info['ColorSpace'] = "/#{colour}"
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
@data = idat
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
@label = label
|
|
289
|
+
|
|
290
|
+
# assign it a place in the named resource dictionary as an external
|
|
291
|
+
# object, according to the label passed in with it.
|
|
292
|
+
@parent.pages << self
|
|
293
|
+
# also make sure that we have the right procset object for it.
|
|
294
|
+
@parent.procset << 'ImageC'
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def to_s
|
|
298
|
+
tmp = @data.dup
|
|
299
|
+
res = "\n#{@oid} 0 obj\n<<"
|
|
300
|
+
@info.each { |k, v| res << "\n/#{k} #{v}"}
|
|
301
|
+
res << "\n/Length #{tmp.size} >>\nstream\n#{tmp}\nendstream\nendobj\n"
|
|
302
|
+
res
|
|
303
|
+
end
|
|
304
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# PDF::Writer for Ruby.
|
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
|
7
|
+
# for full licensing information.
|
|
8
|
+
#
|
|
9
|
+
# $Id$
|
|
10
|
+
#++
|
|
11
|
+
# Define the document information -- metadata.
|
|
12
|
+
class PDF::Writer::Object::Info < PDF::Writer::Object
|
|
13
|
+
Info = %w{CreationDate Creator Title Author Subject Keywords ModDate Trapped Producer}
|
|
14
|
+
def initialize(parent)
|
|
15
|
+
super(parent)
|
|
16
|
+
|
|
17
|
+
@parent.instance_variable_set('@info', self)
|
|
18
|
+
@creationdate = Time.now
|
|
19
|
+
|
|
20
|
+
@creator = File.basename($0)
|
|
21
|
+
@producer = "PDF::Writer for Ruby"
|
|
22
|
+
@title = nil
|
|
23
|
+
@author = nil
|
|
24
|
+
@subject = nil
|
|
25
|
+
@keywords = nil
|
|
26
|
+
@moddate = nil
|
|
27
|
+
@trapped = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
Info.each do |i|
|
|
31
|
+
attr_accessor i.downcase.intern
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_s
|
|
35
|
+
res = "\n#{@oid} 0 obj\n<<\n"
|
|
36
|
+
Info.each do |i|
|
|
37
|
+
v = __send__("#{i.downcase}".intern)
|
|
38
|
+
next if v.nil?
|
|
39
|
+
res << "/#{i} ("
|
|
40
|
+
if v.kind_of?(Time)
|
|
41
|
+
s = "D:%04d%02d%02d%02d%02d"
|
|
42
|
+
v = v.utc
|
|
43
|
+
v = s % [ v.year, v.month, v.day, v.hour, v.min ]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
res << PDF::Writer.escape(v)
|
|
47
|
+
res << ")\n"
|
|
48
|
+
end
|
|
49
|
+
res << ">>\nendobj"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# PDF::Writer for Ruby.
|
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
|
7
|
+
# for full licensing information.
|
|
8
|
+
#
|
|
9
|
+
# $Id$
|
|
10
|
+
#++
|
|
11
|
+
# Define the outlines in the doc, empty for now
|
|
12
|
+
class PDF::Writer::Object::Outline < PDF::Writer::Object
|
|
13
|
+
def initialize(parent, label, title = label)
|
|
14
|
+
super(parent)
|
|
15
|
+
|
|
16
|
+
@action = PDF::Writer::Action.new(parent, label, :ilink)
|
|
17
|
+
@title = title
|
|
18
|
+
|
|
19
|
+
parent.outlines.list << self
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_s
|
|
23
|
+
pos = @parent.outlines.list.index(self)
|
|
24
|
+
res = "\n#{@oid} 0 obj\n<< /Title (#{@title})"
|
|
25
|
+
res << " /Prev #{@parent.outlines.list[pos - 1].oid} 0 R" if pos.nonzero?
|
|
26
|
+
res << " /Next #{@parent.outlines.list[pos + 1].oid} 0 R" if @oid != parent.outlines.list[-1].oid
|
|
27
|
+
res << " /A #{@action.oid} 0 R>>\nendobj"
|
|
28
|
+
res
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# PDF::Writer for Ruby.
|
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
|
7
|
+
# for full licensing information.
|
|
8
|
+
#
|
|
9
|
+
# $Id$
|
|
10
|
+
#++
|
|
11
|
+
# Define the outlines in the doc, empty for now
|
|
12
|
+
class PDF::Writer::Object::Outlines < PDF::Writer::Object
|
|
13
|
+
def initialize(parent)
|
|
14
|
+
super(parent)
|
|
15
|
+
|
|
16
|
+
@list = []
|
|
17
|
+
@parent.catalog.outlines = self
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
attr_reader :list
|
|
21
|
+
|
|
22
|
+
def to_s
|
|
23
|
+
if @list.empty?
|
|
24
|
+
"\n#{@oid} 0 obj\n<< /Type /Outlines >>\nendobj"
|
|
25
|
+
else
|
|
26
|
+
"\n#{@oid} 0 obj\n<< /Type /Outlines /First #{@list[0].oid} 0 R /Last
|
|
27
|
+
#{@list[-1].oid} 0 R>>\nendobj"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# PDF::Writer for Ruby.
|
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
|
7
|
+
# for full licensing information.
|
|
8
|
+
#
|
|
9
|
+
# $Id$
|
|
10
|
+
#++
|
|
11
|
+
# A page object, it also creates a contents object to hold its contents
|
|
12
|
+
class PDF::Writer::Object::Page < PDF::Writer::Object
|
|
13
|
+
# Create a page. The optional +relative+ is a Hash with keys :pos =>
|
|
14
|
+
# :before|:after and :rpage, the page to which this new page will be
|
|
15
|
+
# added relative.
|
|
16
|
+
def initialize(parent, relative = nil)
|
|
17
|
+
super(parent)
|
|
18
|
+
|
|
19
|
+
@parent.current_page = self
|
|
20
|
+
@owner = @parent.instance_variable_get('@current_node')
|
|
21
|
+
@page_number = @parent.pages.size
|
|
22
|
+
@contents = []
|
|
23
|
+
|
|
24
|
+
if relative.nil?
|
|
25
|
+
@parent.pages << self
|
|
26
|
+
else
|
|
27
|
+
relative[:page] = self
|
|
28
|
+
@parent.pages.add(relative)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# make a contents object to go with this page
|
|
32
|
+
@contents << PDF::Writer::Object::Contents.new(@parent, self)
|
|
33
|
+
@parent.instance_variable_set('@current_contents', @contents[-1])
|
|
34
|
+
match = (@parent.pages.size % 2 == 0 ? :even_pages : :odd_pages)
|
|
35
|
+
# Cheat here. I don't want to add an unnecessary attribute.
|
|
36
|
+
@parent.instance_variable_get('@add_loose_objects').each do |obj, target|
|
|
37
|
+
@contents << obj if target == :all_pages or match == target
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
@annotations = []
|
|
41
|
+
|
|
42
|
+
@media_box = nil
|
|
43
|
+
@crop_box = nil
|
|
44
|
+
@bleed_box = nil
|
|
45
|
+
@trim_box = nil
|
|
46
|
+
@art_box = nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
attr_accessor :contents
|
|
50
|
+
attr_reader :page_number
|
|
51
|
+
|
|
52
|
+
def add_annotation(a)
|
|
53
|
+
@annotations << a
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def to_s
|
|
57
|
+
res = "\n#{@oid} 0 obj\n<< /Type /Page\n/Parent #{@owner.oid} 0 R"
|
|
58
|
+
unless @annotations.empty?
|
|
59
|
+
res << "\n/Annots ["
|
|
60
|
+
@annotations.each { |e| res << " #{e.oid} 0 R"}
|
|
61
|
+
res << "]"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
if @contents.size == 1
|
|
65
|
+
res << "\n/Contents #{@contents[0].oid} 0 R"
|
|
66
|
+
else
|
|
67
|
+
res << "\n/Contents [\n"
|
|
68
|
+
@contents.each { |c| res << "#{c.oid} 0 R\n" }
|
|
69
|
+
res << "]"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# MediaBox:: rectangle (Required; inheritable). A rectangle (see
|
|
73
|
+
# Section 3.8.4, �Rectangles�), expressed in default user
|
|
74
|
+
# space units, defining the boundaries of the physical
|
|
75
|
+
# medium on which the page is intended to be displayed or
|
|
76
|
+
# printed (see Section 10.10.1, �Page Boundaries�).
|
|
77
|
+
res << "\n/MediaBox [#{@media_box.join(' ')}]" unless @media_box.nil? or @media_box.empty?
|
|
78
|
+
# CropBox:: rectangle (Optional; inheritable) A rectangle, expressed
|
|
79
|
+
# in default user space units, defining the visible region
|
|
80
|
+
# of default user space. When the page is displayed or
|
|
81
|
+
# printed, its contents are to be clipped (cropped) to
|
|
82
|
+
# this rectangle and then imposed on the output medium in
|
|
83
|
+
# some implementation-defined manner (see Section 10.10.1,
|
|
84
|
+
# �Page Boundaries�). Default value: the value of MediaBox.
|
|
85
|
+
res << "\n/CropBox [#{@crop_box.join(' ')}]" unless @crop_box.nil? or @crop_box.empty?
|
|
86
|
+
# BleedBox:: rectangle (Optional; PDF 1.3) A rectangle, expressed in
|
|
87
|
+
# default user space units, defining the region to which
|
|
88
|
+
# the contents of the page should be clipped when output
|
|
89
|
+
# in a production environment (see Section 10.10.1, �Page
|
|
90
|
+
# Boundaries�). Default value: the value of CropBox.
|
|
91
|
+
res << "\n/BleedBox [#{@bleed_box.join(' ')}]" unless @bleed_box.nil? or @bleed_box.empty?
|
|
92
|
+
# TrimBox:: rectangle (Optional; PDF 1.3) A rectangle, expressed in
|
|
93
|
+
# default user space units, defining the intended
|
|
94
|
+
# dimensions of the finished page after trimming (see
|
|
95
|
+
# Section 10.10.1, �Page Boundaries�). Default value: the
|
|
96
|
+
# value of CropBox.
|
|
97
|
+
res << "\n/TrimBox [#{@trim_box.join(' ')}]" unless @trim_box.nil? or @trim_box.empty?
|
|
98
|
+
# ArtBox:: rectangle (Optional; PDF 1.3) A rectangle, expressed in
|
|
99
|
+
# default user space units, defining the extent of the
|
|
100
|
+
# page�s meaningful content (including potential white
|
|
101
|
+
# space) as intended by the page�s creator (see Section
|
|
102
|
+
# 10.10.1, �Page Boundaries�). Default value: the value of
|
|
103
|
+
# CropBox.
|
|
104
|
+
res << "\n/ArtBox [#{@art_box.join(' ')}]" unless @art_box.nil? or @art_box.empty?
|
|
105
|
+
|
|
106
|
+
res << "\n>>\nendobj"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# BoxColorInfo:: dictionary (Optional; PDF 1.4) A box color information
|
|
111
|
+
# dictionary specifying the colors and other visual
|
|
112
|
+
# characteristics to be used in displaying guidelines on
|
|
113
|
+
# the screen for the various page boundaries (see �Display
|
|
114
|
+
# of Page Boundaries� on page 893). If this entry is
|
|
115
|
+
# absent, the application should use its own current
|
|
116
|
+
# default settings.
|
|
117
|
+
#
|
|
118
|
+
# Rotate:: integer (Optional; inheritable) The number of degrees by
|
|
119
|
+
# which the page should be rotated clockwise when
|
|
120
|
+
# displayed or printed. The value must be a multiple of
|
|
121
|
+
# 90. Default value: 0.
|
|
122
|
+
# Group:: dictionary (Optional; PDF 1.4) A group attributes
|
|
123
|
+
# dictionary specifying the attributes of the page�s page
|
|
124
|
+
# group for use in the transparent imaging model (see
|
|
125
|
+
# Sections 7.3.6, �Page Group,� and 7.5.5, �Transparency
|
|
126
|
+
# Group XObjects�).
|
|
127
|
+
# Thumb:: stream (Optional) A stream object defining the page�s
|
|
128
|
+
# thumbnail image (see Section 8.2.3, �Thumbnail Images�).
|
|
129
|
+
# B:: array (Optional; PDF 1.1; recommended if the page
|
|
130
|
+
# contains article beads) An array of indirect references
|
|
131
|
+
# to article beads appearing on the page (see Section
|
|
132
|
+
# 8.3.2, �Articles�; see also implementation note 37 in
|
|
133
|
+
# Appendix H). The beads are listed in the array in
|
|
134
|
+
# natural reading order.
|
|
135
|
+
# Dur:: number (Optional; PDF 1.1) The page�s display duration
|
|
136
|
+
# (also called its advance timing): the maximum length of
|
|
137
|
+
# time, in seconds, that the page is displayed during
|
|
138
|
+
# presentations before the viewer application
|
|
139
|
+
# automatically advances to the next page (see Section
|
|
140
|
+
# 8.3.3, �Presentations�). By default, the viewer does not
|
|
141
|
+
# advance automatically.
|
|
142
|
+
# Trans:: dictionary (Optional; PDF 1.1) A transition dictionary
|
|
143
|
+
# describing the transition effect to be used when
|
|
144
|
+
# displaying the page during presentations (see Section
|
|
145
|
+
# 8.3.3, �Presentations�).
|
|
146
|
+
# Annots:: array (Optional) An array of annotation dictionaries
|
|
147
|
+
# representing annotations associated with the page (see
|
|
148
|
+
# Section 8.4, �Annotations�).
|
|
149
|
+
# AA:: dictionary (Optional; PDF 1.2) An additional-actions
|
|
150
|
+
# dictionary defining actions to be performed when the
|
|
151
|
+
# page is opened or closed (see Section 8.5.2, �Trigger
|
|
152
|
+
# Events�; see also implementation note 38 in Appendix H).
|
|
153
|
+
# Metadata:: stream (Optional; PDF 1.4) A metadata stream containing
|
|
154
|
+
# metadata for the page (see Section 10.2.2, �Metadata
|
|
155
|
+
# Streams�).
|
|
156
|
+
# PieceInfo:: dictionary (Optional; PDF 1.3) A page-piece dictionary
|
|
157
|
+
# associated with the page (see Section 10.4, �Page-Piece
|
|
158
|
+
# Dictionaries�).
|
|
159
|
+
# StructParents:: integer (Required if the page contains structural
|
|
160
|
+
# content items; PDF 1.3) The integer key of the page�s
|
|
161
|
+
# entry in the structural parent tree (see �Finding
|
|
162
|
+
# Structure Elements from Content Items� on page 797).
|
|
163
|
+
# ID:: string (Optional; PDF 1.3; indirect reference preferred)
|
|
164
|
+
# The digital identifier of the page�s parent Web Capture
|
|
165
|
+
# content set (see Section 10.9.5, �Object Attributes
|
|
166
|
+
# Related to Web Capture�).
|
|
167
|
+
# PZ:: number (Optional; PDF 1.3) The page�s preferred zoom
|
|
168
|
+
# (magnification) factor: the factor by which it should be
|
|
169
|
+
# scaled to achieve the natural display magnification (see
|
|
170
|
+
# Section 10.9.5, �Object Attributes Related to Web
|
|
171
|
+
# Capture�).
|
|
172
|
+
# SeparationInfo:: dictionary (Optional; PDF 1.3) A separation dictionary
|
|
173
|
+
# containing information needed to generate color
|
|
174
|
+
# separations for the page (see Section 10.10.3,
|
|
175
|
+
# �Separation Dictionaries�).
|
|
176
|
+
# Tabs:: name (Optional; PDF 1.5) A name specifying the tab order
|
|
177
|
+
# to be used for annotations on the page. The possible
|
|
178
|
+
# values are R (row order), C (column order), and S
|
|
179
|
+
# (structure order). See Section 8.4, �Annotations,� for
|
|
180
|
+
# details.
|
|
181
|
+
# TemplateInstantiated:: name (Required if this page was created from a
|
|
182
|
+
# named page object; PDF 1.5) The name of the
|
|
183
|
+
# originating page object (see Section 8.6.5,
|
|
184
|
+
# �Named Pages�).
|
|
185
|
+
# PresSteps:: dictionary (Optional; PDF 1.5) A navigation node
|
|
186
|
+
# dictionary representing the first node on the page (see
|
|
187
|
+
# �Sub-page Navigation� on page 566).
|
|
188
|
+
# UserUnit:: number (Optional; PDF 1.6) A positive number giving the
|
|
189
|
+
# size of default user space units, in multiples of 1/72
|
|
190
|
+
# inch. The range of supported values is
|
|
191
|
+
# implementation-dependent; see implementation note 171 in
|
|
192
|
+
# Appendix H. Default value: 1.0 (user unit is 1/72 inch).
|
|
193
|
+
# VP:: dictionary (Optional; PDF 1.6) An array of viewport
|
|
194
|
+
# dictionaries (see Table 8.105) specifying rectangular
|
|
195
|
+
# regions of the page.
|