prawn 0.14.0 → 0.15.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 +4 -4
- data/.yardopts +2 -1
- data/Rakefile +12 -0
- data/lib/prawn.rb +9 -21
- data/lib/prawn/document.rb +95 -68
- data/lib/prawn/document/bounding_box.rb +22 -4
- data/lib/prawn/document/column_box.rb +2 -0
- data/lib/prawn/document/graphics_state.rb +1 -1
- data/lib/prawn/document/internals.rb +2 -2
- data/lib/prawn/document/snapshot.rb +2 -1
- data/lib/prawn/document/span.rb +2 -0
- data/lib/prawn/encoding.rb +1 -1
- data/lib/prawn/font.rb +89 -75
- data/lib/prawn/font/afm.rb +3 -0
- data/lib/prawn/font/dfont.rb +1 -0
- data/lib/prawn/font/ttf.rb +2 -0
- data/lib/prawn/font_metric_cache.rb +3 -1
- data/lib/prawn/graphics.rb +2 -14
- data/lib/prawn/graphics/cap_style.rb +1 -0
- data/lib/prawn/graphics/color.rb +1 -0
- data/lib/prawn/graphics/dash.rb +3 -2
- data/lib/prawn/graphics/join_style.rb +2 -0
- data/lib/prawn/graphics/patterns.rb +1 -0
- data/lib/prawn/graphics/transformation.rb +1 -0
- data/lib/prawn/graphics/transparency.rb +2 -0
- data/lib/prawn/image_handler.rb +2 -0
- data/lib/prawn/images.rb +5 -0
- data/lib/prawn/images/image.rb +1 -0
- data/lib/prawn/images/jpg.rb +3 -0
- data/lib/prawn/images/png.rb +2 -0
- data/lib/prawn/layout.rb +8 -13
- data/lib/prawn/layout/grid.rb +15 -3
- data/lib/prawn/measurement_extensions.rb +4 -0
- data/lib/prawn/measurements.rb +2 -0
- data/lib/prawn/outline.rb +3 -1
- data/lib/prawn/repeater.rb +3 -1
- data/lib/prawn/security.rb +15 -7
- data/lib/prawn/security/arcfour.rb +52 -0
- data/lib/prawn/soft_mask.rb +3 -1
- data/lib/prawn/stamp.rb +2 -0
- data/lib/prawn/table.rb +2 -0
- data/lib/prawn/table/cell.rb +4 -1
- data/lib/prawn/table/cell/image.rb +1 -2
- data/lib/prawn/table/cell/in_table.rb +2 -0
- data/lib/prawn/table/cell/span_dummy.rb +1 -0
- data/lib/prawn/table/cells.rb +7 -2
- data/lib/prawn/table/column_width_calculator.rb +8 -2
- data/lib/prawn/text.rb +4 -2
- data/lib/prawn/text/box.rb +3 -0
- data/lib/prawn/text/formatted/arranger.rb +2 -0
- data/lib/prawn/text/formatted/box.rb +55 -50
- data/lib/prawn/text/formatted/fragment.rb +2 -0
- data/lib/prawn/text/formatted/line_wrap.rb +1 -0
- data/lib/prawn/text/formatted/parser.rb +2 -0
- data/lib/prawn/text/formatted/wrap.rb +2 -0
- data/lib/prawn/utilities.rb +5 -3
- data/manual/graphics/common_lines.rb +2 -0
- data/manual/text/group.rb +2 -0
- data/manual/text/text.rb +1 -1
- data/prawn.gemspec +4 -3
- data/spec/grid_spec.rb +11 -0
- data/spec/object_store_spec.rb +1 -96
- data/spec/reference_spec.rb +0 -57
- data/spec/spec_helper.rb +7 -0
- data/spec/table_spec.rb +26 -0
- metadata +172 -185
- data/lib/pdf/core.rb +0 -35
- data/lib/pdf/core/annotations.rb +0 -60
- data/lib/pdf/core/byte_string.rb +0 -9
- data/lib/pdf/core/destinations.rb +0 -90
- data/lib/pdf/core/document_state.rb +0 -79
- data/lib/pdf/core/filter_list.rb +0 -51
- data/lib/pdf/core/filters.rb +0 -36
- data/lib/pdf/core/graphics_state.rb +0 -89
- data/lib/pdf/core/literal_string.rb +0 -16
- data/lib/pdf/core/name_tree.rb +0 -177
- data/lib/pdf/core/object_store.rb +0 -311
- data/lib/pdf/core/outline.rb +0 -315
- data/lib/pdf/core/page.rb +0 -212
- data/lib/pdf/core/page_geometry.rb +0 -126
- data/lib/pdf/core/pdf_object.rb +0 -99
- data/lib/pdf/core/reference.rb +0 -103
- data/lib/pdf/core/stream.rb +0 -98
- data/lib/pdf/core/text.rb +0 -275
- data/lib/prawn/templates.rb +0 -75
- data/spec/filters_spec.rb +0 -34
- data/spec/name_tree_spec.rb +0 -112
- data/spec/pdf_object_spec.rb +0 -172
- data/spec/stream_spec.rb +0 -58
- data/spec/template_spec_obsolete.rb +0 -352
data/lib/pdf/core/outline.rb
DELETED
@@ -1,315 +0,0 @@
|
|
1
|
-
module PDF
|
2
|
-
module Core
|
3
|
-
# The Outline class organizes the outline tree items for the document.
|
4
|
-
# Note that the prev and parent instance variables are adjusted while navigating
|
5
|
-
# through the nested blocks. These variables along with the presence or absense
|
6
|
-
# of blocks are the primary means by which the relations for the various
|
7
|
-
# OutlineItems and the OutlineRoot are set. Unfortunately, the best way to
|
8
|
-
# understand how this works is to follow the method calls through a real example.
|
9
|
-
#
|
10
|
-
# Some ideas for the organization of this class were gleaned from name_tree. In
|
11
|
-
# particular the way in which the OutlineItems are finally rendered into document
|
12
|
-
# objects in PdfObject through a hash.
|
13
|
-
#
|
14
|
-
class Outline
|
15
|
-
|
16
|
-
extend Forwardable
|
17
|
-
def_delegator :@document, :page_number
|
18
|
-
|
19
|
-
attr_accessor :parent
|
20
|
-
attr_accessor :prev
|
21
|
-
attr_accessor :document
|
22
|
-
attr_accessor :items
|
23
|
-
|
24
|
-
def initialize(document)
|
25
|
-
@document = document
|
26
|
-
@parent = root
|
27
|
-
@prev = nil
|
28
|
-
@items = {}
|
29
|
-
end
|
30
|
-
|
31
|
-
# Defines/Updates an outline for the document.
|
32
|
-
# The outline is an optional nested index that appears on the side of a PDF
|
33
|
-
# document usually with direct links to pages. The outline DSL is defined by nested
|
34
|
-
# blocks involving two methods: section and page; see the documentation on those methods
|
35
|
-
# for their arguments and options. Note that one can also use outline#update
|
36
|
-
# to add more sections to the end of the outline tree using the same syntax and scope.
|
37
|
-
#
|
38
|
-
# The syntax is best illustrated with an example:
|
39
|
-
#
|
40
|
-
# Prawn::Document.generate(outlined_document.pdf) do
|
41
|
-
# text "Page 1. This is the first Chapter. "
|
42
|
-
# start_new_page
|
43
|
-
# text "Page 2. More in the first Chapter. "
|
44
|
-
# start_new_page
|
45
|
-
# outline.define do
|
46
|
-
# section 'Chapter 1', :destination => 1, :closed => true do
|
47
|
-
# page :destination => 1, :title => 'Page 1'
|
48
|
-
# page :destination => 2, :title => 'Page 2'
|
49
|
-
# end
|
50
|
-
# end
|
51
|
-
# start_new_page do
|
52
|
-
# outline.update do
|
53
|
-
# section 'Chapter 2', :destination => 2, do
|
54
|
-
# page :destination => 3, :title => 'Page 3'
|
55
|
-
# end
|
56
|
-
# end
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
def define(&block)
|
60
|
-
instance_eval(&block) if block
|
61
|
-
end
|
62
|
-
|
63
|
-
alias :update :define
|
64
|
-
|
65
|
-
# Inserts an outline section to the outline tree (see outline#define).
|
66
|
-
# Although you will probably choose to exclusively use outline#define so
|
67
|
-
# that your outline tree is contained and easy to manage, this method
|
68
|
-
# gives you the option to insert sections to the outline tree at any point
|
69
|
-
# during document generation. This method allows you to add a child subsection
|
70
|
-
# to any other item at any level in the outline tree.
|
71
|
-
# Currently the only way to locate the place of entry is with the title for the
|
72
|
-
# item. If your title names are not unique consider using define_outline.
|
73
|
-
# The method takes the following arguments:
|
74
|
-
# title: a string that must match an outline title to add the subsection to
|
75
|
-
# position: either :first or :last(the default) where the subsection will be placed relative
|
76
|
-
# to other child elements. If you need to position your subsection in between
|
77
|
-
# other elements then consider using #insert_section_after
|
78
|
-
# block: uses the same DSL syntax as outline#define, for example:
|
79
|
-
#
|
80
|
-
# Consider using this method inside of outline.update if you want to have the outline object
|
81
|
-
# to be scoped as self (see #insert_section_after example).
|
82
|
-
#
|
83
|
-
# go_to_page 2
|
84
|
-
# start_new_page
|
85
|
-
# text "Inserted Page"
|
86
|
-
# outline.add_subsection_to :title => 'Page 2', :first do
|
87
|
-
# outline.page :destination => page_number, :title => "Inserted Page"
|
88
|
-
# end
|
89
|
-
#
|
90
|
-
def add_subsection_to(title, position = :last, &block)
|
91
|
-
@parent = items[title]
|
92
|
-
raise Prawn::Errors::UnknownOutlineTitle,
|
93
|
-
"\n No outline item with title: '#{title}' exists in the outline tree" unless @parent
|
94
|
-
@prev = position == :first ? nil : @parent.data.last
|
95
|
-
nxt = position == :first ? @parent.data.first : nil
|
96
|
-
insert_section(nxt, &block)
|
97
|
-
end
|
98
|
-
|
99
|
-
# Inserts an outline section to the outline tree (see outline#define).
|
100
|
-
# Although you will probably choose to exclusively use outline#define so
|
101
|
-
# that your outline tree is contained and easy to manage, this method
|
102
|
-
# gives you the option to insert sections to the outline tree at any point
|
103
|
-
# during document generation. Unlike outline.add_section, this method allows
|
104
|
-
# you to enter a section after any other item at any level in the outline tree.
|
105
|
-
# Currently the only way to locate the place of entry is with the title for the
|
106
|
-
# item. If your title names are not unique consider using define_outline.
|
107
|
-
# The method takes the following arguments:
|
108
|
-
# title: the title of other section or page to insert new section after
|
109
|
-
# block: uses the same DSL syntax as outline#define, for example:
|
110
|
-
#
|
111
|
-
# go_to_page 2
|
112
|
-
# start_new_page
|
113
|
-
# text "Inserted Page"
|
114
|
-
# update_outline do
|
115
|
-
# insert_section_after :title => 'Page 2' do
|
116
|
-
# page :destination => page_number, :title => "Inserted Page"
|
117
|
-
# end
|
118
|
-
# end
|
119
|
-
#
|
120
|
-
def insert_section_after(title, &block)
|
121
|
-
@prev = items[title]
|
122
|
-
raise Prawn::Errors::UnknownOutlineTitle,
|
123
|
-
"\n No outline item with title: '#{title}' exists in the outline tree" unless @prev
|
124
|
-
@parent = @prev.data.parent
|
125
|
-
nxt = @prev.data.next
|
126
|
-
insert_section(nxt, &block)
|
127
|
-
end
|
128
|
-
|
129
|
-
# See outline#define above for documentation on how this is used in that context
|
130
|
-
#
|
131
|
-
# Adds an outine section to the outline tree.
|
132
|
-
# Although you will probably choose to exclusively use outline#define so
|
133
|
-
# that your outline tree is contained and easy to manage, this method
|
134
|
-
# gives you the option to add sections to the outline tree at any point
|
135
|
-
# during document generation. When not being called from within another #section block
|
136
|
-
# the section will be added at the top level after the other root elements of the outline.
|
137
|
-
# For more flexible placement try using outline#insert_section_after and/or
|
138
|
-
# outline#add_subsection_to
|
139
|
-
# Takes the following arguments:
|
140
|
-
# title: the outline text that appears for the section.
|
141
|
-
# options: destination - optional integer defining the page number for a destination link
|
142
|
-
# to the top of the page (using a :FIT destination).
|
143
|
-
# - or an array with a custom destination (see the #dest_* methods of the
|
144
|
-
# PDF::Destination module)
|
145
|
-
# closed - whether the section should show its nested outline elements.
|
146
|
-
# - defaults to false.
|
147
|
-
# block: more nested subsections and/or page blocks
|
148
|
-
#
|
149
|
-
# example usage:
|
150
|
-
#
|
151
|
-
# outline.section 'Added Section', :destination => 3 do
|
152
|
-
# outline.page :destionation => 3, :title => 'Page 3'
|
153
|
-
# end
|
154
|
-
def section(title, options = {}, &block)
|
155
|
-
add_outline_item(title, options, &block)
|
156
|
-
end
|
157
|
-
|
158
|
-
# See Outline#define above for more documentation on how it is used in that context
|
159
|
-
#
|
160
|
-
# Adds a page to the outline.
|
161
|
-
# Although you will probably choose to exclusively use outline#define so
|
162
|
-
# that your outline tree is contained and easy to manage, this method also
|
163
|
-
# gives you the option to add pages to the root of outline tree at any point
|
164
|
-
# during document generation. Note that the page will be added at the
|
165
|
-
# top level after the other root outline elements. For more flexible placement try
|
166
|
-
# using outline#insert_section_after and/or outline#add_subsection_to.
|
167
|
-
#
|
168
|
-
# Takes the following arguments:
|
169
|
-
# options:
|
170
|
-
# title - REQUIRED. The outline text that appears for the page.
|
171
|
-
# destination - optional integer defining the page number for a destination link
|
172
|
-
# to the top of the page (using a :FIT destination).
|
173
|
-
# - or an array with a custom destination (see the #dest_* methods of the
|
174
|
-
# PDF::Destination module)
|
175
|
-
# closed - whether the section should show its nested outline elements.
|
176
|
-
# - defaults to false.
|
177
|
-
# example usage:
|
178
|
-
#
|
179
|
-
# outline.page :title => "Very Last Page"
|
180
|
-
# Note: this method is almost identical to section except that it does not accept a block
|
181
|
-
# thereby defining the outline item as a leaf on the outline tree structure.
|
182
|
-
def page(options = {})
|
183
|
-
if options[:title]
|
184
|
-
title = options[:title]
|
185
|
-
else
|
186
|
-
raise Prawn::Errors::RequiredOption,
|
187
|
-
"\nTitle is a required option for page"
|
188
|
-
end
|
189
|
-
add_outline_item(title, options)
|
190
|
-
end
|
191
|
-
|
192
|
-
private
|
193
|
-
|
194
|
-
# The Outline dictionary (12.3.3) for this document. It is
|
195
|
-
# lazily initialized, so that documents that do not have an outline
|
196
|
-
# do not incur the additional overhead.
|
197
|
-
def root
|
198
|
-
document.state.store.root.data[:Outlines] ||= document.ref!(OutlineRoot.new)
|
199
|
-
end
|
200
|
-
|
201
|
-
def add_outline_item(title, options, &block)
|
202
|
-
outline_item = create_outline_item(title, options)
|
203
|
-
set_relations(outline_item)
|
204
|
-
increase_count
|
205
|
-
set_variables_for_block(outline_item, block)
|
206
|
-
block.call if block
|
207
|
-
reset_parent(outline_item)
|
208
|
-
end
|
209
|
-
|
210
|
-
def create_outline_item(title, options)
|
211
|
-
outline_item = OutlineItem.new(title, parent, options)
|
212
|
-
|
213
|
-
case options[:destination]
|
214
|
-
when Integer
|
215
|
-
page_index = options[:destination] - 1
|
216
|
-
outline_item.dest = [document.state.pages[page_index].dictionary, :Fit]
|
217
|
-
when Array
|
218
|
-
outline_item.dest = options[:destination]
|
219
|
-
end
|
220
|
-
|
221
|
-
outline_item.prev = prev if @prev
|
222
|
-
items[title] = document.ref!(outline_item)
|
223
|
-
end
|
224
|
-
|
225
|
-
def set_relations(outline_item)
|
226
|
-
prev.data.next = outline_item if prev
|
227
|
-
parent.data.first = outline_item unless prev
|
228
|
-
parent.data.last = outline_item
|
229
|
-
end
|
230
|
-
|
231
|
-
def increase_count
|
232
|
-
counting_parent = parent
|
233
|
-
while counting_parent
|
234
|
-
counting_parent.data.count += 1
|
235
|
-
if counting_parent == root
|
236
|
-
counting_parent = nil
|
237
|
-
else
|
238
|
-
counting_parent = counting_parent.data.parent
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
def set_variables_for_block(outline_item, block)
|
244
|
-
self.prev = block ? nil : outline_item
|
245
|
-
self.parent = outline_item if block
|
246
|
-
end
|
247
|
-
|
248
|
-
def reset_parent(outline_item)
|
249
|
-
if parent == outline_item
|
250
|
-
self.prev = outline_item
|
251
|
-
self.parent = outline_item.data.parent
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
def insert_section(nxt, &block)
|
256
|
-
last = @parent.data.last
|
257
|
-
if block
|
258
|
-
block.call
|
259
|
-
end
|
260
|
-
adjust_relations(nxt, last)
|
261
|
-
reset_root_positioning
|
262
|
-
end
|
263
|
-
|
264
|
-
def adjust_relations(nxt, last)
|
265
|
-
if nxt
|
266
|
-
nxt.data.prev = @prev
|
267
|
-
@prev.data.next = nxt
|
268
|
-
@parent.data.last = last
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
def reset_root_positioning
|
273
|
-
@parent = root
|
274
|
-
@prev = root.data.last
|
275
|
-
end
|
276
|
-
|
277
|
-
end
|
278
|
-
|
279
|
-
class OutlineRoot #:nodoc:
|
280
|
-
attr_accessor :count, :first, :last
|
281
|
-
|
282
|
-
def initialize
|
283
|
-
@count = 0
|
284
|
-
end
|
285
|
-
|
286
|
-
def to_hash
|
287
|
-
{:Type => :Outlines, :Count => count, :First => first, :Last => last}
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
class OutlineItem #:nodoc:
|
292
|
-
attr_accessor :count, :first, :last, :next, :prev, :parent, :title, :dest, :closed
|
293
|
-
|
294
|
-
def initialize(title, parent, options)
|
295
|
-
@closed = options[:closed]
|
296
|
-
@title = title
|
297
|
-
@parent = parent
|
298
|
-
@count = 0
|
299
|
-
end
|
300
|
-
|
301
|
-
def to_hash
|
302
|
-
hash = { :Title => title,
|
303
|
-
:Parent => parent,
|
304
|
-
:Count => closed ? -count : count }
|
305
|
-
[{:First => first}, {:Last => last}, {:Next => defined?(@next) && @next},
|
306
|
-
{:Prev => prev}, {:Dest => dest}].each do |h|
|
307
|
-
unless h.values.first.nil?
|
308
|
-
hash.merge!(h)
|
309
|
-
end
|
310
|
-
end
|
311
|
-
hash
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
315
|
-
end
|
data/lib/pdf/core/page.rb
DELETED
@@ -1,212 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# prawn/core/page.rb : Implements low-level representation of a PDF page
|
4
|
-
#
|
5
|
-
# Copyright February 2010, Gregory Brown. All Rights Reserved.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
#
|
9
|
-
|
10
|
-
require_relative 'graphics_state'
|
11
|
-
|
12
|
-
module PDF
|
13
|
-
module Core
|
14
|
-
class Page #:nodoc:
|
15
|
-
attr_accessor :document, :margins, :stack
|
16
|
-
attr_writer :content, :dictionary
|
17
|
-
|
18
|
-
def initialize(document, options={})
|
19
|
-
@document = document
|
20
|
-
@margins = options[:margins] || { :left => 36,
|
21
|
-
:right => 36,
|
22
|
-
:top => 36,
|
23
|
-
:bottom => 36 }
|
24
|
-
@stack = GraphicStateStack.new(options[:graphic_state])
|
25
|
-
if options[:object_id]
|
26
|
-
init_from_object(options)
|
27
|
-
else
|
28
|
-
init_new_page(options)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def graphic_state
|
33
|
-
stack.current_state
|
34
|
-
end
|
35
|
-
|
36
|
-
def layout
|
37
|
-
return @layout if defined?(@layout) && @layout
|
38
|
-
|
39
|
-
mb = dictionary.data[:MediaBox]
|
40
|
-
if mb[3] > mb[2]
|
41
|
-
:portrait
|
42
|
-
else
|
43
|
-
:landscape
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def size
|
48
|
-
defined?(@size) && @size || dimensions[2,2]
|
49
|
-
end
|
50
|
-
|
51
|
-
def in_stamp_stream?
|
52
|
-
!!@stamp_stream
|
53
|
-
end
|
54
|
-
|
55
|
-
def stamp_stream(dictionary)
|
56
|
-
@stamp_stream = ""
|
57
|
-
@stamp_dictionary = dictionary
|
58
|
-
graphic_stack_size = stack.stack.size
|
59
|
-
|
60
|
-
document.save_graphics_state
|
61
|
-
document.send(:freeze_stamp_graphics)
|
62
|
-
yield if block_given?
|
63
|
-
|
64
|
-
until graphic_stack_size == stack.stack.size
|
65
|
-
document.restore_graphics_state
|
66
|
-
end
|
67
|
-
|
68
|
-
@stamp_dictionary << @stamp_stream
|
69
|
-
|
70
|
-
@stamp_stream = nil
|
71
|
-
@stamp_dictionary = nil
|
72
|
-
end
|
73
|
-
|
74
|
-
def content
|
75
|
-
@stamp_stream || document.state.store[@content]
|
76
|
-
end
|
77
|
-
|
78
|
-
# As per the PDF spec, each page can have multiple content streams. This will
|
79
|
-
# add a fresh, empty content stream this the page, mainly for use in loading
|
80
|
-
# template files.
|
81
|
-
#
|
82
|
-
def new_content_stream
|
83
|
-
return if in_stamp_stream?
|
84
|
-
|
85
|
-
unless dictionary.data[:Contents].is_a?(Array)
|
86
|
-
dictionary.data[:Contents] = [content]
|
87
|
-
end
|
88
|
-
@content = document.ref({})
|
89
|
-
dictionary.data[:Contents] << document.state.store[@content]
|
90
|
-
document.open_graphics_state
|
91
|
-
end
|
92
|
-
|
93
|
-
def dictionary
|
94
|
-
defined?(@stamp_dictionary) && @stamp_dictionary || document.state.store[@dictionary]
|
95
|
-
end
|
96
|
-
|
97
|
-
def resources
|
98
|
-
if dictionary.data[:Resources]
|
99
|
-
document.deref(dictionary.data[:Resources])
|
100
|
-
else
|
101
|
-
dictionary.data[:Resources] = {}
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def fonts
|
106
|
-
if resources[:Font]
|
107
|
-
document.deref(resources[:Font])
|
108
|
-
else
|
109
|
-
resources[:Font] = {}
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
def xobjects
|
114
|
-
if resources[:XObject]
|
115
|
-
document.deref(resources[:XObject])
|
116
|
-
else
|
117
|
-
resources[:XObject] = {}
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def ext_gstates
|
122
|
-
if resources[:ExtGState]
|
123
|
-
document.deref(resources[:ExtGState])
|
124
|
-
else
|
125
|
-
resources[:ExtGState] = {}
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def finalize
|
130
|
-
if dictionary.data[:Contents].is_a?(Array)
|
131
|
-
dictionary.data[:Contents].each do |stream|
|
132
|
-
stream.stream.compress! if document.compression_enabled?
|
133
|
-
end
|
134
|
-
else
|
135
|
-
content.stream.compress! if document.compression_enabled?
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def imported_page?
|
140
|
-
@imported_page
|
141
|
-
end
|
142
|
-
|
143
|
-
def dimensions
|
144
|
-
return inherited_dictionary_value(:MediaBox) if imported_page?
|
145
|
-
|
146
|
-
coords = PDF::Core::PageGeometry::SIZES[size] || size
|
147
|
-
[0,0] + case(layout)
|
148
|
-
when :portrait
|
149
|
-
coords
|
150
|
-
when :landscape
|
151
|
-
coords.reverse
|
152
|
-
else
|
153
|
-
raise PDF::Core::Errors::InvalidPageLayout,
|
154
|
-
"Layout must be either :portrait or :landscape"
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
private
|
159
|
-
|
160
|
-
def init_from_object(options)
|
161
|
-
@dictionary = options[:object_id].to_i
|
162
|
-
dictionary.data[:Parent] = document.state.store.pages if options[:page_template]
|
163
|
-
|
164
|
-
unless dictionary.data[:Contents].is_a?(Array) # content only on leafs
|
165
|
-
@content = dictionary.data[:Contents].identifier
|
166
|
-
end
|
167
|
-
|
168
|
-
@stamp_stream = nil
|
169
|
-
@stamp_dictionary = nil
|
170
|
-
@imported_page = true
|
171
|
-
end
|
172
|
-
|
173
|
-
def init_new_page(options)
|
174
|
-
@size = options[:size] || "LETTER"
|
175
|
-
@layout = options[:layout] || :portrait
|
176
|
-
|
177
|
-
@stamp_stream = nil
|
178
|
-
@stamp_dictionary = nil
|
179
|
-
@imported_page = false
|
180
|
-
|
181
|
-
@content = document.ref({})
|
182
|
-
content << "q" << "\n"
|
183
|
-
@dictionary = document.ref(:Type => :Page,
|
184
|
-
:Parent => document.state.store.pages,
|
185
|
-
:MediaBox => dimensions,
|
186
|
-
:Contents => content)
|
187
|
-
|
188
|
-
resources[:ProcSet] = [:PDF, :Text, :ImageB, :ImageC, :ImageI]
|
189
|
-
end
|
190
|
-
|
191
|
-
# some entries in the Page dict can be inherited from parent Pages dicts.
|
192
|
-
#
|
193
|
-
# Starting with the current page dict, this method will walk up the
|
194
|
-
# inheritance chain return the first value that is found for key
|
195
|
-
#
|
196
|
-
# inherited_dictionary_value(:MediaBox)
|
197
|
-
# => [ 0, 0, 595, 842 ]
|
198
|
-
#
|
199
|
-
def inherited_dictionary_value(key, local_dict = nil)
|
200
|
-
local_dict ||= dictionary.data
|
201
|
-
|
202
|
-
if local_dict.has_key?(key)
|
203
|
-
local_dict[key]
|
204
|
-
elsif local_dict.has_key?(:Parent)
|
205
|
-
inherited_dictionary_value(key, local_dict[:Parent].data)
|
206
|
-
else
|
207
|
-
nil
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|