File Coverage

blib/lib/PDF/API2/Page.pm
Criterion Covered Total %
statement 181 237 76.3
branch 49 96 51.0
condition 20 67 29.8
subroutine 33 40 82.5
pod 20 28 71.4
total 303 468 64.7


line stmt bran cond sub pod time code
1             package PDF::API2::Page;
2              
3 38     38   300 use base 'PDF::API2::Basic::PDF::Pages';
  38         79  
  38         5188  
4              
5 38     38   271 use strict;
  38         84  
  38         933  
6 38     38   239 use warnings;
  38         172  
  38         1982  
7              
8             our $VERSION = '2.043'; # VERSION
9              
10 38     38   254 use Carp;
  38         90  
  38         3284  
11 38     38   324 use POSIX qw(floor);
  38         74  
  38         277  
12 38     38   2953 use Scalar::Util qw(looks_like_number weaken);
  38         145  
  38         1998  
13              
14 38     38   236 use PDF::API2::Basic::PDF::Utils;
  38         77  
  38         2550  
15 38     38   27371 use PDF::API2::Content;
  38         127  
  38         2028  
16 38     38   19389 use PDF::API2::Content::Text;
  38         107  
  38         1185  
17 38     38   295 use PDF::API2::Util;
  38         87  
  38         115819  
18              
19             my $page_sizes = {
20             # Metric A
21             '4a0' => [ 4760, 6716 ],
22             '2a0' => [ 3368, 4760 ],
23             'a0' => [ 2380, 3368 ],
24             'a1' => [ 1684, 2380 ],
25             'a2' => [ 1190, 1684 ],
26             'a3' => [ 842, 1190 ],
27             'a4' => [ 595, 842 ],
28             'a5' => [ 421, 595 ],
29             'a6' => [ 297, 421 ],
30              
31             # Metric B
32             '4b0' => [ 5656, 8000 ],
33             '2b0' => [ 4000, 5656 ],
34             'b0' => [ 2828, 4000 ],
35             'b1' => [ 2000, 2828 ],
36             'b2' => [ 1414, 2000 ],
37             'b3' => [ 1000, 1414 ],
38             'b4' => [ 707, 1000 ],
39             'b5' => [ 500, 707 ],
40             'b6' => [ 353, 500 ],
41              
42             # US
43             'letter' => [ 612, 792 ],
44             'legal' => [ 612, 1008 ],
45             'ledger' => [ 1224, 792 ],
46             'tabloid' => [ 792, 1224 ],
47             };
48              
49             =head1 NAME
50              
51             PDF::API2::Page - Methods to interact with individual pages
52              
53             =head1 SYNOPSIS
54              
55             my $pdf = PDF::API2->new();
56              
57             # Add a page to a new or existing PDF
58             my $page = $pdf->page();
59              
60             # Set the page size
61             $page->size('letter');
62              
63             # Set prepress page boundaries
64             $page->boundaries(media => '12x18', trim => 0.5 * 72);
65              
66             # Add an image
67             my $image = $pdf->image('/path/to/file.jpg');
68             $page->object($image, $x, $y, $w, $h);
69              
70             # Add textual content
71             my $text = $page->text();
72              
73             # Add graphical content (paths and shapes)
74             my $canvas = $page->graphics();
75              
76             =cut
77              
78             sub new {
79 142     142 1 376 my ($class, $pdf, $parent, $index) = @_;
80 142         250 my $self = {};
81              
82 142 50       358 $class = ref($class) if ref($class);
83 142         609 $self = $class->SUPER::new($pdf, $parent);
84 142         414 $self->{'Type'} = PDFName('Page');
85 142         619 $self->proc_set(qw( PDF Text ImageB ImageC ImageI ));
86 142         540 delete $self->{'Count'};
87 142         311 delete $self->{'Kids'};
88 142         530 $parent->add_page($self, $index);
89 142         400 return $self;
90             }
91              
92             sub coerce {
93 0     0 0 0 my ($class, $pdf, $page) = @_;
94 0         0 my $self = $page;
95 0         0 bless $self, $class;
96 0         0 $self->{' apipdf'} = $pdf;
97 0         0 weaken $self->{' apipdf'};
98 0         0 return $self;
99             }
100              
101             # Deprecated. Marking the page as dirty should only be needed in rare cases
102             # when the page hash is being edited directly rather than through the API. In
103             # that case, the out_obj call can be made manually. There's no reason (that I
104             # can think of) to have a specific call just (and only) for Page objects.
105             sub update {
106 0     0 0 0 my $self = shift();
107 0         0 $self->{' apipdf'}->out_obj($self);
108 0         0 return $self;
109             }
110              
111             =head1 METHODS
112              
113             =head2 size
114              
115             # Set the page size using a common name
116             $page->size('letter');
117              
118             # Set the page size using coordinates in points (X1, Y1, X2, Y2)
119             $page->size([0, 0, 612, 792]);
120              
121             # Get the page coordinates in points
122             my @rectangle = $page->size();
123              
124             Set the physical page size (a.k.a. media box) when called with an argument.
125             See L below for possible values. Returns the C<$page> object.
126              
127             Returns the coordinates of the rectangle enclosing the physical page size when
128             called without arguments.
129              
130             The size method is a convenient shortcut for setting the PDF's media box when
131             print-related page boundaries aren't required. It's equivalent to the
132             following:
133              
134             # Set
135             $page = $page->boundaries(media => $size);
136              
137             # Get
138             @rectangle = $page->boundaries->{'media'}->@*;
139              
140             =cut
141              
142             sub size {
143 1     1 1 2559 my $self = shift();
144              
145             # Set
146 1 50       5 if (@_) {
147 1         5 return $self->boundaries(media => @_);
148             }
149              
150             # Get
151 0         0 my %boundaries = $self->boundaries();
152 0         0 return @{$boundaries{'media'}};
  0         0  
153             }
154              
155             =head2 boundaries
156              
157             # Set
158             $page->boundaries(
159             media => '13x19',
160             bleed => [0.75 * 72, 0.75 * 72, 12.25 * 72, 18.25 * 72],
161             trim => 0.25 * 72,
162             );
163              
164             # Get
165             %boundaries = $page->boundaries();
166             ($x1, $y1, $x2, $y2) = $page->boundaries('trim');
167              
168             Set prepress page boundaries when called with a hash containing one or more page
169             boundary definitions. Returns the C<$page> object.
170              
171             Returns the current page boundaries if called without arguments. Returns the
172             coordinates for the specified page boundary if called with one argument.
173              
174             =head3 Page Boundaries
175              
176             PDF defines five page boundaries. When creating PDFs for print shops, you'll
177             most commonly use just the media box and trim box. Traditional print shops may
178             also use the bleed box when adding printer's marks and other information.
179              
180             =over
181              
182             =item * media
183              
184             The media box defines the boundaries of the physical medium on which the page is
185             to be printed. It may include any extended area surrounding the finished page
186             for bleed, printing marks, or other such purposes. The default value is a US
187             letter page (8.5" x 11").
188              
189             =item * crop
190              
191             The crop box defines the region to which the contents of the page shall be
192             clipped (cropped) when displayed or printed. The default value is the page's
193             media box.
194              
195             This is a historical page boundary. You'll likely want to set the bleed and/or
196             trim boxes instead.
197              
198             =item * bleed
199              
200             The bleed box defines the region to which the contents of the page shall be
201             clipped when output in a production environment. This may include any extra
202             bleed area needed to accommodate the physical limitations of cutting, folding,
203             and trimming equipment. The actual printed page (media box) may include
204             printing marks that fall outside the bleed box. The default value is the page's
205             crop box.
206              
207             =item * trim
208              
209             The trim box defines the intended dimensions of the finished page after
210             trimming. It may be smaller than the media box to allow for production-related
211             content, such as printing instructions, cut marks, or color bars. The default
212             value is the page's crop box.
213              
214             =item * art
215              
216             The art box defines the extent of the page's meaningful content (including
217             potential white space) as intended by the page's creator. The default value is
218             the page's crop box.
219              
220             =back
221              
222             =head3 Page Sizes
223              
224             PDF page sizes are stored as rectangle coordinates. For convenience, PDF::API2
225             also supports a number of aliases and shortcuts that are more human-friendly.
226              
227             The following formats are available:
228              
229             =over
230              
231             =item * a standard paper size
232              
233             $page->boundaries(media => 'A4');
234              
235             Aliases for the most common paper sizes are built in (case-insensitive).
236              
237             US: Letter, Legal, Ledger, Tabloid
238              
239             Metric: 4A0, 2A0, A0 - A6, 4B0, 2B0, and B0 - B6
240              
241             =item * a "WxH" string in inches
242              
243             $page->boundaries(media => '8.5x11');
244              
245             Many US paper sizes are commonly identified by their size in inches rather than
246             by a particular name. These can be passed as strings with the width and height
247             separated by an C.
248              
249             Examples: C<4x6>, C<12x18>, C<8.5x11>
250              
251             =item * a number (in points) representing a reduction from the next-larger box
252              
253             # Note: There are 72 points per inch
254             $page->boundaries(media => '12x18', trim => 0.5 * 72);
255              
256             # Equivalent
257             $page->boundaries(media => [0, 0, 12 * 72, 18 * 72],
258             trim => [0.5 * 72, 0.5 * 72, 11.5 * 72, 17.5 * 72]);
259              
260             This example shows a 12" x 18" physical sheet that will be reduced to a final
261             size of 11" x 17" by trimming 0.5" from each edge. The smaller boundary is
262             assumed to be centered on the larger one.
263              
264             The "next-larger box" follows this order, stopping at the first defined value:
265              
266             art -> trim -> bleed -> media
267              
268             crop -> media
269              
270             This option isn't available for the media box since it is by definition the
271             largest boundary.
272              
273             =item * [$width, $height] in points
274              
275             $page->boundaries(media => [8.5 * 72, 11 * 7.2]);
276              
277             For other page or boundary sizes, the width and height (in points) can be given
278             directly as an array.
279              
280             =item * [$x1, $y1, $x2, $y2] in points
281              
282             $page->boundaries(media => [0, 0, 8.5 * 72, 11 * 72]);
283              
284             Finally, the raw coordinates of the bottom-left and top-right corners of a
285             rectangle can be specified.
286              
287             =back
288              
289             =cut
290              
291             sub _to_rectangle {
292 6     6   9 my $value = shift();
293              
294             # An array of two or four numbers in points
295 6 50       13 if (ref($value) eq 'ARRAY') {
296 0 0       0 if (@$value == 2) {
    0          
297 0         0 return (0, 0, @$value);
298             }
299             elsif (@$value == 4) {
300 0         0 return @$value;
301             }
302 0         0 croak "Page boundary array must contain two or four numbers";
303             }
304              
305             # WxH in inches
306 6 100       27 if ($value =~ /^([0-9.]+)\s*x\s*([0-9.]+)$/) {
307 2         8 my ($w, $h) = ($1, $2);
308 2 50 33     17 if (looks_like_number($w) and looks_like_number($h)) {
309 2         9 return (0, 0, $w * 72, $h * 72);
310             }
311             }
312              
313             # Common names for page sizes
314 4 50       16 if ($page_sizes->{lc $value}) {
315 4         5 return (0, 0, @{$page_sizes->{lc $value}});
  4         13  
316             }
317              
318 0 0       0 if (ref($value)) {
319 0         0 croak "Unrecognized page size";
320             }
321             else {
322 0         0 croak "Unrecognized page size: $value";
323             }
324             }
325              
326             sub boundaries {
327 6     6 1 5198 my $self = shift();
328              
329             # Get
330 6 50 33     23 unless (@_) {
331 0         0 my %boundaries;
332 0         0 foreach my $box (qw(Media Crop Bleed Trim Art)) {
333 0         0 $boundaries{lc($box)} = [$self->_bounding_box($box . 'Box')];
334             }
335 0         0 return %boundaries;
336             }
337             elsif (@_ == 1) {
338             my $box = shift();
339             my @coordinates = $self->_bounding_box(ucfirst($box) . 'Box');
340             return @coordinates;
341             }
342              
343             # Set
344 6         19 my %boxes = @_;
345 6         13 foreach my $box (qw(media crop bleed trim art)) {
346 30 100       63 next unless exists $boxes{$box};
347              
348             # Special case: A single number as the value for anything other than
349             # MediaBox means to take the next larger size and reduce it by this
350             # amount in points on all four sides, provided the larger size was also
351             # included.
352 8         17 my $value = $boxes{$box};
353 8         8 my @rectangle;
354 8 100 66     35 if ($box ne 'media' and not ref($value) and looks_like_number($value)) {
      66        
355 2 50       10 my $parent = ($box eq 'crop' ? 'media' :
    50          
    50          
356             $box eq 'bleed' ? 'media' :
357             $box eq 'trim' ? 'bleed' : 'trim');
358 2 50 33     6 $parent = 'bleed' if $parent eq 'trim' and not $boxes{'trim'};
359 2 50 33     10 $parent = 'media' if $parent eq 'bleed' and not $boxes{'bleed'};
360 2 50 33     7 $parent = 'media' if $parent eq 'bleed' and not $boxes{'bleed'};
361 2 50       6 unless ($boxes{$parent}) {
362 0         0 croak "Single-number argument for $box requires $parent";
363             }
364              
365 2         3 @rectangle = @{$boxes{$parent}};
  2         5  
366 2         5 $rectangle[0] += $value;
367 2         3 $rectangle[1] += $value;
368 2         4 $rectangle[2] -= $value;
369 2         2 $rectangle[3] -= $value;
370             }
371             else {
372 6         15 @rectangle = _to_rectangle($value);
373             }
374              
375 8         23 my $box_name = ucfirst($box) . 'Box';
376 8         24 $self->_bounding_box($box_name, @rectangle);
377 8         24 $boxes{$box} = [@rectangle];
378             }
379              
380             # Get
381              
382 6         20 return $self;
383             }
384              
385             sub _bounding_box {
386 92     92   2865 my $self = shift();
387 92         134 my $type = shift();
388              
389             # Get
390 92 100       204 unless (scalar @_) {
391 46         142 my $box = $self->find_prop($type);
392 46 50       116 unless ($box) {
393             # Default to letter (for historical PDF::API2 reasons, not per the
394             # PDF specification)
395 0 0       0 return (0, 0, 612, 792) if $type eq 'MediaBox';
396              
397             # Use defaults per PDF 1.7 section 14.11.2 Page Boundaries
398 0 0       0 return $self->_bounding_box('MediaBox') if $type eq 'CropBox';
399 0         0 return $self->_bounding_box('CropBox');
400             }
401 46         116 return map { $_->val() } $box->elements();
  184         356  
402             }
403              
404             # Set
405 46         113 $self->{$type} = PDFArray(map { PDFNum(float($_)) } page_size(@_));
  184         408  
406 46         137 return $self;
407             }
408              
409             # Deprecated; use size(...) or boundaries('media', ...)
410             sub mediabox {
411 38     38 1 85587 my $self = shift();
412 38 50       118 return $self->_bounding_box('MediaBox') unless @_;
413 38         138 return $self->_bounding_box('MediaBox', page_size(@_));
414             }
415              
416             # Deprecated
417             sub get_mediabox {
418 34     34 1 147 my $self = shift();
419 34         61 return $self->_bounding_box('MediaBox');
420             }
421              
422             # Deprecated; use boundaries('crop', ...)
423             sub cropbox {
424 1     1 1 2549 my $self = shift();
425 1 50       5 return $self->_bounding_box('CropBox') unless @_;
426 1         5 return $self->_bounding_box('CropBox', page_size(@_));
427             }
428              
429             # Deprecated
430             sub get_cropbox {
431 2     2 1 10 my $self = shift();
432 2         5 return $self->_bounding_box('CropBox');
433             }
434              
435             # Deprecated; use boundaries('bleed', ...)
436             sub bleedbox {
437 1     1 1 2607 my $self = shift();
438 1 50       5 return $self->_bounding_box('BleedBox') unless @_;
439 1         4 return $self->_bounding_box('BleedBox', page_size(@_));
440             }
441              
442             # Deprecated
443             sub get_bleedbox {
444 2     2 1 12 my $self = shift();
445 2         5 return $self->_bounding_box('BleedBox');
446             }
447              
448             # Deprecated; use boundaries('trim', ...)
449             sub trimbox {
450 1     1 1 2591 my $self = shift();
451 1 50       5 return $self->_bounding_box('TrimBox') unless @_;
452 1         6 return $self->_bounding_box('TrimBox', page_size(@_));
453             }
454              
455             # Deprecated
456             sub get_trimbox {
457 2     2 1 9 my $self = shift();
458 2         6 return $self->_bounding_box('TrimBox');
459             }
460              
461             # Deprecated; use boundaries('art', ...)
462             sub artbox {
463 1     1 1 2533 my $self = shift();
464 1 50       5 return $self->_bounding_box('ArtBox') unless @_;
465 1         5 return $self->_bounding_box('ArtBox', page_size(@_));
466             }
467              
468             # Deprecated
469             sub get_artbox {
470 2     2 1 10 my $self = shift();
471 2         4 return $self->_bounding_box('ArtBox');
472             }
473              
474             =head2 rotation
475              
476             $page = $page->rotation($degrees);
477              
478             Rotates the page clockwise when displayed or printed. C<$degrees> must be a
479             multiple of 90 and may be negative for counter-clockwise rotation.
480              
481             The coordinate system follows the page rotation. In other words, after rotating
482             the page 180 degrees, [0, 0] will be in the top right corner of the page rather
483             than the bottom left, X will increase to the right, and Y will increase
484             downward.
485              
486             To create a landscape page without moving the origin, use L.
487              
488             =cut
489              
490             # Deprecated (renamed to follow the pattern of using nouns instead of verbs)
491 0     0 1 0 sub rotate { return rotation(@_) }
492              
493             sub rotation {
494 0     0 1 0 my ($self, $degrees) = @_;
495 0   0     0 $degrees //= 0;
496              
497             # Ignore rotation of 360 or more (in either direction)
498 0         0 $degrees = $degrees % 360;
499              
500 0 0 0     0 unless ( $degrees == 0
      0        
      0        
      0        
      0        
      0        
501             or $degrees == 90 or $degrees == -90
502             or $degrees == 180 or $degrees == -180
503             or $degrees == 270 or $degrees == -270) {
504 0         0 croak "Rotation must be a multiple of 90 degrees";
505             }
506              
507 0         0 $self->{'Rotate'} = PDFNum($degrees);
508              
509 0         0 return $self;
510             }
511              
512             =head2 graphics
513              
514             my $canvas = $page->graphics(%options);
515              
516             Returns a L object for drawing paths and shapes.
517              
518             The following options are available:
519              
520             =over
521              
522             =item * prepend (boolean)
523              
524             If true, place the drawing at the beginning of the page's content stream instead
525             of the end.
526              
527             =item * compress (boolean)
528              
529             Manually specify whether the drawing instructions should be compressed. If
530             unspecified, the PDF's compression setting will be used, which is on by default.
531              
532             =back
533              
534             =cut
535              
536             sub fixcontents {
537 128     128 0 216 my $self = shift();
538 128   66     489 $self->{'Contents'} = $self->{'Contents'} || PDFArray();
539 128 50       516 if (ref($self->{'Contents'}) =~ /Objind$/) {
540 0         0 $self->{'Contents'}->realise();
541             }
542 128 50       672 if (ref($self->{'Contents'}) !~ /Array$/) {
543 0         0 $self->{'Contents'} = PDFArray($self->{'Contents'});
544             }
545 128         248 return;
546             }
547              
548             sub content {
549 122     122 0 296 my ($self, $obj, $dir) = @_;
550 122 50 33     382 if (defined($dir) and $dir > 0) {
551 0         0 $self->precontent($obj);
552             }
553             else {
554 122         303 $self->addcontent($obj);
555             }
556 122 50       477 $self->{' apipdf'}->new_obj($obj) unless $obj->is_obj($self->{' apipdf'});
557 122         288 $obj->{' apipdf'} = $self->{' apipdf'};
558 122         272 $obj->{' api'} = $self->{' api'};
559 122         232 $obj->{' apipage'} = $self;
560              
561 122         400 weaken $obj->{' apipdf'};
562 122         329 weaken $obj->{' api'};
563 122         278 weaken $obj->{' apipage'};
564              
565 122         460 return $obj;
566             }
567              
568             sub addcontent {
569 122     122 0 270 my ($self, @objs) = @_;
570 122         351 $self->fixcontents();
571 122         411 $self->{'Contents'}->add_elements(@objs);
572 122         220 return;
573             }
574              
575             sub precontent {
576 0     0 0 0 my ($self, @objs) = @_;
577 0         0 $self->fixcontents();
578 0         0 unshift @{$self->{'Contents'}->val()}, @objs;
  0         0  
579 0         0 return;
580             }
581              
582             # Deprecated; replace with graphics, which adds input validation
583             sub gfx {
584 52     52 1 528 my ($self, $prepend) = @_;
585 52         158 my $graphics = $self->graphics(prepend => $prepend);
586              
587             # Delete the input validation flag
588 52         102 delete $graphics->{' graphics'};
589              
590 52         223 return $graphics;
591             }
592              
593             sub graphics {
594 104     104 1 296 my ($self, %options) = @_;
595 104         584 my $graphics = PDF::API2::Content->new();
596 104         200 $graphics->{' graphics'} = 1;
597              
598 104   66     508 $options{'compress'} //= $self->{' api'}->{'forcecompress'};
599 104 100       285 $graphics->compressFlate() if $options{'compress'};
600              
601 104 50       239 if ($options{'prepend'}) {
602 0         0 return $self->content($graphics, 1);
603             }
604             else {
605 104         288 return $self->content($graphics);
606             }
607             }
608              
609             =head2 text
610              
611             my $text = $page->text(%options);
612              
613             Returns a L object for including textual content.
614              
615             The options are the same as the L method.
616              
617             =cut
618              
619             sub text {
620 18     18 1 899 my $self = shift();
621              
622 18         28 my %options;
623 18 50       47 if (@_ == 1) {
624             # Deprecated
625 0         0 $options{'prepend'} = shift();
626             }
627             else {
628 18         34 %options = @_;
629             }
630              
631 18         132 my $text = PDF::API2::Content::Text->new();
632              
633 18   66     108 $options{'compress'} //= $self->{' api'}->{'forcecompress'};
634 18 100       68 $text->compressFlate() if $options{'compress'};
635              
636 18 50       50 if ($options{'prepend'}) {
637 0         0 $self->content($text, 1);
638             }
639             else {
640 18         59 $self->content($text);
641             }
642              
643 18         64 return $text;
644             }
645              
646             =head2 object
647              
648             $page = $page->object($object, $x, $y, $scale_x, $scale_y);
649              
650             Places an image or other external object (a.k.a. XObject) on the page in the
651             specified location.
652              
653             For images, C<$scale_x> and C<$scale_y> represent the width and height of the
654             image on the page in points. If C<$scale_x> is omitted, it will default to 72
655             pixels per inch. If C<$scale_y> is omitted, the image will be scaled
656             proportionally based on the image dimensions.
657              
658             For other external objects, the scale is a multiplier, where 1 (the default)
659             represents 100% (i.e. no change).
660              
661             If the object to be placed depends on a coordinate transformation (e.g. rotation
662             or skew), first create a content object using L, then call
663             L after making the appropriate transformations.
664              
665             =cut
666              
667             sub object {
668 0     0 1 0 my $self = shift();
669 0         0 $self->graphics->object(@_);
670 0         0 return $self;
671             }
672              
673             =head2 annotation
674              
675             my $annotation = $page->annotation();
676              
677             Returns a new L object.
678              
679             =cut
680              
681             sub annotation {
682 6     6 1 42 my $self = shift();
683              
684 6 100 33     21 unless (exists $self->{'Annots'}) {
685 5         12 $self->{'Annots'} = PDFArray();
686 5         15 $self->{' apipdf'}->out_obj($self);
687             }
688             elsif (ref($self->{'Annots'}) =~ /Objind/) {
689             $self->{'Annots'}->realise();
690             }
691              
692 6         585 require PDF::API2::Annotation;
693 6         31 my $ant = PDF::API2::Annotation->new();
694 6         19 $self->{'Annots'}->add_elements($ant);
695 6         24 $self->{' apipdf'}->new_obj($ant);
696 6         15 $ant->{' apipdf'} = $self->{' apipdf'};
697 6         10 $ant->{' apipage'} = $self;
698 6         19 weaken $ant->{' apipdf'};
699 6         18 weaken $ant->{' apipage'};
700              
701 6 100       14 if ($self->{'Annots'}->is_obj($self->{' apipdf'})) {
702 1         5 $self->{' apipdf'}->out_obj($self->{'Annots'});
703             }
704              
705 6         28 return $ant;
706             }
707              
708             sub resource {
709 29     29 0 90 my ($self, $type, $key, $obj, $force) = @_;
710 29         112 my $dict = $self->find_prop('Resources');
711              
712 29   0     159 $dict = $dict || $self->{'Resources'} || PDFDict();
713              
714 29 50       145 $dict->realise() if ref($dict) =~ /Objind$/;
715              
716 29   66     208 $dict->{$type} = $dict->{$type} || PDFDict();
717 29 50       171 $dict->{$type}->realise if ref($dict->{$type}) =~ /Objind$/;
718              
719 29 50       100 unless (defined $obj) {
720 0   0       return $dict->{$type}->{$key} || undef;
721             }
722             else {
723 29 50       72 if ($force) {
724 0         0 $dict->{$type}->{$key} = $obj;
725             }
726             else {
727 29   33     165 $dict->{$type}->{$key} = $dict->{$type}->{$key} || $obj;
728             }
729              
730 29 50       144 $self->{' apipdf'}->out_obj($dict) if $dict->is_obj($self->{' apipdf'});
731 29 50       133 $self->{' apipdf'}->out_obj($dict->{$type}) if $dict->{$type}->is_obj($self->{' apipdf'});
732 29 50       115 $self->{' apipdf'}->out_obj($obj) if $obj->is_obj($self->{' apipdf'});
733 29         143 $self->{' apipdf'}->out_obj($self);
734              
735 29         89 return $dict;
736             }
737             }
738              
739             sub ship_out {
740 0     0 0   my ($self, $pdf) = @_;
741              
742 0           $pdf->ship_out($self);
743 0 0         if (defined $self->{'Contents'}) {
744 0           $pdf->ship_out($self->{'Contents'}->elements());
745             }
746 0           return $self;
747             }
748              
749             =head1 MIGRATION
750              
751             See L for an overview.
752              
753             =over
754              
755             =item gfx
756              
757             Replace with L.
758              
759             =item rotate
760              
761             Replace with L.
762              
763             =item mediabox
764              
765             =item get_mediabox
766              
767             Replace with L if not in a print shop environment or L
768             if more complex page boundaries are needed.
769              
770             If using page size aliases (e.g. "letter" or "A4"), check the Page Sizes section
771             to ensure that the alias you're using is still supported (you'll get an error if
772             it isn't).
773              
774             =item cropbox
775              
776             =item bleedbox
777              
778             =item trimbox
779              
780             =item artbox
781              
782             =item get_cropbox
783              
784             =item get_bleedbox
785              
786             =item get_trimbox
787              
788             =item get_artbox
789              
790             Replace with L.
791              
792             =back
793              
794             =cut
795              
796             1;