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.
Files changed (86) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +1 -0
  3. data/ChangeLog +113 -0
  4. data/Demo-README +43 -0
  5. data/Gemfile +4 -0
  6. data/LICENCE +131 -0
  7. data/README +33 -0
  8. data/Rakefile +1 -0
  9. data/Release-Announcement +87 -0
  10. data/bin/techbook +24 -0
  11. data/bugs/first_page_margins.rb +28 -0
  12. data/bugs/page_numbering_simple.rb +14 -0
  13. data/bugs/page_numbering_stop_and_start.rb +21 -0
  14. data/demo/chunkybacon.rb +36 -0
  15. data/demo/code.rb +71 -0
  16. data/demo/colornames.rb +47 -0
  17. data/demo/demo.rb +73 -0
  18. data/demo/gettysburg.rb +66 -0
  19. data/demo/hello.rb +26 -0
  20. data/demo/individual-i.rb +89 -0
  21. data/demo/pac.rb +70 -0
  22. data/demo/qr-language.rb +580 -0
  23. data/demo/qr-library.rb +380 -0
  24. data/images/bluesmoke.jpg +0 -0
  25. data/images/chunkybacon.jpg +0 -0
  26. data/images/chunkybacon.png +0 -0
  27. data/lib/pdf/charts.rb +13 -0
  28. data/lib/pdf/charts/stddev.rb +431 -0
  29. data/lib/pdf/core_ext/mutex.rb +11 -0
  30. data/lib/pdf/math.rb +108 -0
  31. data/lib/pdf/quickref.rb +333 -0
  32. data/lib/pdf/simpletable.rb +948 -0
  33. data/lib/pdf/techbook.rb +905 -0
  34. data/lib/pdf/writer.rb +2734 -0
  35. data/lib/pdf/writer/arc4.rb +63 -0
  36. data/lib/pdf/writer/fontmetrics.rb +203 -0
  37. data/lib/pdf/writer/fonts/Courier-Bold.afm +342 -0
  38. data/lib/pdf/writer/fonts/Courier-BoldOblique.afm +342 -0
  39. data/lib/pdf/writer/fonts/Courier-Oblique.afm +342 -0
  40. data/lib/pdf/writer/fonts/Courier.afm +342 -0
  41. data/lib/pdf/writer/fonts/Helvetica-Bold.afm +2827 -0
  42. data/lib/pdf/writer/fonts/Helvetica-BoldOblique.afm +2827 -0
  43. data/lib/pdf/writer/fonts/Helvetica-Oblique.afm +3051 -0
  44. data/lib/pdf/writer/fonts/Helvetica.afm +3051 -0
  45. data/lib/pdf/writer/fonts/MustRead.html +19 -0
  46. data/lib/pdf/writer/fonts/Symbol.afm +213 -0
  47. data/lib/pdf/writer/fonts/Times-Bold.afm +2588 -0
  48. data/lib/pdf/writer/fonts/Times-BoldItalic.afm +2384 -0
  49. data/lib/pdf/writer/fonts/Times-Italic.afm +2667 -0
  50. data/lib/pdf/writer/fonts/Times-Roman.afm +2419 -0
  51. data/lib/pdf/writer/fonts/ZapfDingbats.afm +225 -0
  52. data/lib/pdf/writer/graphics.rb +817 -0
  53. data/lib/pdf/writer/graphics/imageinfo.rb +365 -0
  54. data/lib/pdf/writer/lang.rb +43 -0
  55. data/lib/pdf/writer/lang/en.rb +99 -0
  56. data/lib/pdf/writer/object.rb +23 -0
  57. data/lib/pdf/writer/object/action.rb +35 -0
  58. data/lib/pdf/writer/object/annotation.rb +42 -0
  59. data/lib/pdf/writer/object/catalog.rb +39 -0
  60. data/lib/pdf/writer/object/contents.rb +70 -0
  61. data/lib/pdf/writer/object/destination.rb +40 -0
  62. data/lib/pdf/writer/object/encryption.rb +53 -0
  63. data/lib/pdf/writer/object/font.rb +72 -0
  64. data/lib/pdf/writer/object/fontdescriptor.rb +34 -0
  65. data/lib/pdf/writer/object/fontencoding.rb +40 -0
  66. data/lib/pdf/writer/object/image.rb +304 -0
  67. data/lib/pdf/writer/object/info.rb +51 -0
  68. data/lib/pdf/writer/object/outline.rb +30 -0
  69. data/lib/pdf/writer/object/outlines.rb +30 -0
  70. data/lib/pdf/writer/object/page.rb +195 -0
  71. data/lib/pdf/writer/object/pages.rb +115 -0
  72. data/lib/pdf/writer/object/procset.rb +46 -0
  73. data/lib/pdf/writer/object/viewerpreferences.rb +74 -0
  74. data/lib/pdf/writer/ohash.rb +58 -0
  75. data/lib/pdf/writer/oreader.rb +25 -0
  76. data/lib/pdf/writer/state.rb +48 -0
  77. data/lib/pdf/writer/strokestyle.rb +138 -0
  78. data/manual.pwd +5965 -0
  79. data/metaconfig +13 -0
  80. data/pdf-writer.gemspec +28 -0
  81. data/pre-setup.rb +56 -0
  82. data/setup.rb +1366 -0
  83. data/test/helper.rb +4 -0
  84. data/test/test_image_info.rb +16 -0
  85. data/test/test_page_numbering.rb +13 -0
  86. 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.