File Coverage

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


line stmt bran cond sub pod time code
1             package PDF::API2::Page;
2              
3 39     39   314 use base 'PDF::API2::Basic::PDF::Pages';
  39         112  
  39         6052  
4              
5 39     39   270 use strict;
  39         81  
  39         1043  
6 39     39   180 use warnings;
  39         79  
  39         3006  
7              
8             our $VERSION = '2.048'; # VERSION
9              
10 39     39   239 use Carp;
  39         81  
  39         3129  
11 39     39   239 use POSIX qw(floor);
  39         117  
  39         357  
12 39     39   3288 use Scalar::Util qw(looks_like_number weaken);
  39         86  
  39         2245  
13              
14 39     39   253 use PDF::API2::Basic::PDF::Utils;
  39         86  
  39         3570  
15 39     39   30252 use PDF::API2::Content;
  39         178  
  39         2314  
16 39     39   20487 use PDF::API2::Content::Text;
  39         138  
  39         1565  
17 39     39   247 use PDF::API2::Util;
  39         86  
  39         133368  
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 480 my ($class, $pdf, $parent, $index) = @_;
80 142         271 my $self = {};
81              
82 142 50       369 $class = ref($class) if ref($class);
83 142         767 $self = $class->SUPER::new($pdf, $parent);
84 142         544 $self->{'Type'} = PDFName('Page');
85 142         691 $self->proc_set(qw( PDF Text ImageB ImageC ImageI ));
86 142         590 delete $self->{'Count'};
87 142         376 delete $self->{'Kids'};
88 142         747 $parent->add_page($self, $index);
89 142         459 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 3904 my $self = shift();
144              
145             # Set
146 1 50       15 if (@_) {
147 1         7 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 or replace all prepress page boundaries when called with a hash containing
169             one or more page 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   10 my $value = shift();
293              
294             # An array of two or four numbers in points
295 6 50       19 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       36 if ($value =~ /^([0-9.]+)\s*x\s*([0-9.]+)$/) {
307 2         10 my ($w, $h) = ($1, $2);
308 2 50 33     25 if (looks_like_number($w) and looks_like_number($h)) {
309 2         12 return (0, 0, $w * 72, $h * 72);
310             }
311             }
312              
313             # Common names for page sizes
314 4 50       18 if ($page_sizes->{lc $value}) {
315 4         7 return (0, 0, @{$page_sizes->{lc $value}});
  4         18  
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 7691 my $self = shift();
328              
329             # Get
330 6 50 33     34 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         25 my %boxes = @_;
345 6         19 foreach my $box (qw(media crop bleed trim art)) {
346 30 100       83 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         16 my $value = $boxes{$box};
353 8         13 my @rectangle;
354 8 100 66     46 if ($box ne 'media' and not ref($value) and looks_like_number($value)) {
      66        
355 2 50       14 my $parent = ($box eq 'crop' ? 'media' :
    50          
    50          
356             $box eq 'bleed' ? 'media' :
357             $box eq 'trim' ? 'bleed' : 'trim');
358 2 50 33     9 $parent = 'bleed' if $parent eq 'trim' and not $boxes{'trim'};
359 2 50 33     13 $parent = 'media' if $parent eq 'bleed' and not $boxes{'bleed'};
360 2 50 33     9 $parent = 'media' if $parent eq 'bleed' and not $boxes{'bleed'};
361 2 50       7 unless ($boxes{$parent}) {
362 0         0 croak "Single-number argument for $box requires $parent";
363             }
364              
365 2         5 @rectangle = @{$boxes{$parent}};
  2         7  
366 2         7 $rectangle[0] += $value;
367 2         4 $rectangle[1] += $value;
368 2         4 $rectangle[2] -= $value;
369 2         3 $rectangle[3] -= $value;
370             }
371             else {
372 6         19 @rectangle = _to_rectangle($value);
373             }
374              
375 8         24 my $box_name = ucfirst($box) . 'Box';
376 8         29 $self->_bounding_box($box_name, @rectangle);
377 8         35 $boxes{$box} = [@rectangle];
378             }
379              
380 6         26 return $self;
381             }
382              
383             sub _bounding_box {
384 92     92   4060 my $self = shift();
385 92         171 my $type = shift();
386              
387             # Get
388 92 100       233 unless (scalar @_) {
389 46         186 my $box = $self->find_prop($type);
390 46 50       124 unless ($box) {
391             # Default to letter (for historical PDF::API2 reasons, not per the
392             # PDF specification)
393 0 0       0 return (0, 0, 612, 792) if $type eq 'MediaBox';
394              
395             # Use defaults per PDF 1.7 section 14.11.2 Page Boundaries
396 0 0       0 return $self->_bounding_box('MediaBox') if $type eq 'CropBox';
397 0         0 return $self->_bounding_box('CropBox');
398             }
399 46         137 return map { $_->val() } $box->elements();
  184         471  
400             }
401              
402             # Set
403 46         126 $self->{$type} = PDFArray(map { PDFNum(float($_)) } page_size(@_));
  184         506  
404 46         158 return $self;
405             }
406              
407             # Deprecated; use size(...) or boundaries('media', ...)
408             sub mediabox {
409 38     38 1 130145 my $self = shift();
410 38 50       171 return $self->_bounding_box('MediaBox') unless @_;
411 38         203 return $self->_bounding_box('MediaBox', page_size(@_));
412             }
413              
414             # Deprecated
415             sub get_mediabox {
416 34     34 1 170 my $self = shift();
417 34         121 return $self->_bounding_box('MediaBox');
418             }
419              
420             # Deprecated; use boundaries('crop', ...)
421             sub cropbox {
422 1     1 1 3919 my $self = shift();
423 1 50       6 return $self->_bounding_box('CropBox') unless @_;
424 1         6 return $self->_bounding_box('CropBox', page_size(@_));
425             }
426              
427             # Deprecated
428             sub get_cropbox {
429 2     2 1 16 my $self = shift();
430 2         8 return $self->_bounding_box('CropBox');
431             }
432              
433             # Deprecated; use boundaries('bleed', ...)
434             sub bleedbox {
435 1     1 1 3857 my $self = shift();
436 1 50       7 return $self->_bounding_box('BleedBox') unless @_;
437 1         6 return $self->_bounding_box('BleedBox', page_size(@_));
438             }
439              
440             # Deprecated
441             sub get_bleedbox {
442 2     2 1 16 my $self = shift();
443 2         9 return $self->_bounding_box('BleedBox');
444             }
445              
446             # Deprecated; use boundaries('trim', ...)
447             sub trimbox {
448 1     1 1 3854 my $self = shift();
449 1 50       7 return $self->_bounding_box('TrimBox') unless @_;
450 1         6 return $self->_bounding_box('TrimBox', page_size(@_));
451             }
452              
453             # Deprecated
454             sub get_trimbox {
455 2     2 1 15 my $self = shift();
456 2         8 return $self->_bounding_box('TrimBox');
457             }
458              
459             # Deprecated; use boundaries('art', ...)
460             sub artbox {
461 1     1 1 7069 my $self = shift();
462 1 50       7 return $self->_bounding_box('ArtBox') unless @_;
463 1         6 return $self->_bounding_box('ArtBox', page_size(@_));
464             }
465              
466             # Deprecated
467             sub get_artbox {
468 2     2 1 15 my $self = shift();
469 2         10 return $self->_bounding_box('ArtBox');
470             }
471              
472             =head2 rotation
473              
474             $page = $page->rotation($degrees);
475              
476             Rotates the page clockwise when displayed or printed. C<$degrees> must be a
477             multiple of 90 and may be negative for counter-clockwise rotation.
478              
479             The coordinate system follows the page rotation. In other words, after rotating
480             the page 180 degrees, [0, 0] will be in the top right corner of the page rather
481             than the bottom left, X will increase to the right, and Y will increase
482             downward.
483              
484             To create a landscape page without moving the origin, use L.
485              
486             =cut
487              
488             # Deprecated (renamed to follow the pattern of using nouns instead of verbs)
489 0     0 1 0 sub rotate { return rotation(@_) }
490              
491             sub rotation {
492 0     0 1 0 my ($self, $degrees) = @_;
493 0   0     0 $degrees //= 0;
494              
495             # Ignore rotation of 360 or more (in either direction)
496 0         0 $degrees = $degrees % 360;
497              
498 0 0 0     0 unless ( $degrees == 0
      0        
      0        
      0        
      0        
      0        
499             or $degrees == 90 or $degrees == -90
500             or $degrees == 180 or $degrees == -180
501             or $degrees == 270 or $degrees == -270) {
502 0         0 croak "Rotation must be a multiple of 90 degrees";
503             }
504              
505 0         0 $self->{'Rotate'} = PDFNum($degrees);
506              
507 0         0 return $self;
508             }
509              
510             =head2 graphics
511              
512             my $canvas = $page->graphics(%options);
513              
514             Returns a L object for drawing paths and shapes.
515              
516             The following options are available:
517              
518             =over
519              
520             =item * prepend (boolean)
521              
522             If true, place the drawing at the beginning of the page's content stream instead
523             of the end.
524              
525             =item * compress (boolean)
526              
527             Manually specify whether the drawing instructions should be compressed. If
528             unspecified, the PDF's compression setting will be used, which is on by default.
529              
530             =back
531              
532             =cut
533              
534             sub fixcontents {
535 128     128 0 207 my $self = shift();
536 128   66     638 $self->{'Contents'} = $self->{'Contents'} || PDFArray();
537 128 50       647 if (ref($self->{'Contents'}) =~ /Objind$/) {
538 0         0 $self->{'Contents'}->realise();
539             }
540 128 50       782 if (ref($self->{'Contents'}) !~ /Array$/) {
541 0         0 $self->{'Contents'} = PDFArray($self->{'Contents'});
542             }
543 128         295 return;
544             }
545              
546             sub content {
547 122     122 0 1648 my ($self, $obj, $dir) = @_;
548 122 50 33     476 if (defined($dir) and $dir > 0) {
549 0         0 $self->precontent($obj);
550             }
551             else {
552 122         441 $self->addcontent($obj);
553             }
554 122 50       564 $self->{' apipdf'}->new_obj($obj) unless $obj->is_obj($self->{' apipdf'});
555 122         305 $obj->{' apipdf'} = $self->{' apipdf'};
556 122         286 $obj->{' api'} = $self->{' api'};
557 122         368 $obj->{' apipage'} = $self;
558              
559 122         318 weaken $obj->{' apipdf'};
560 122         243 weaken $obj->{' api'};
561 122         352 weaken $obj->{' apipage'};
562              
563 122         493 return $obj;
564             }
565              
566             sub addcontent {
567 122     122 0 308 my ($self, @objs) = @_;
568 122         468 $self->fixcontents();
569 122         420 $self->{'Contents'}->add_elements(@objs);
570 122         227 return;
571             }
572              
573             sub precontent {
574 0     0 0 0 my ($self, @objs) = @_;
575 0         0 $self->fixcontents();
576 0         0 unshift @{$self->{'Contents'}->val()}, @objs;
  0         0  
577 0         0 return;
578             }
579              
580             # Deprecated; replace with graphics, which adds input validation
581             sub gfx {
582 52     52 1 573 my ($self, $prepend) = @_;
583 52         194 my $graphics = $self->graphics(prepend => $prepend);
584              
585             # Delete the input validation flag
586 52         107 delete $graphics->{' graphics'};
587              
588 52         241 return $graphics;
589             }
590              
591             sub graphics {
592 104     104 1 391 my ($self, %options) = @_;
593 104         978 my $graphics = PDF::API2::Content->new();
594 104         283 $graphics->{' graphics'} = 1;
595              
596 104   33     756 $options{'compress'} //= $self->{' api'}->{'forcecompress'};
597 104 100       390 $graphics->compressFlate() if $options{'compress'};
598              
599 104 50       289 if ($options{'prepend'}) {
600 0         0 return $self->content($graphics, 1);
601             }
602             else {
603 104         423 return $self->content($graphics);
604             }
605             }
606              
607             =head2 text
608              
609             my $text = $page->text(%options);
610              
611             Returns a L object for including textual content.
612              
613             The options are the same as the L method.
614              
615             =cut
616              
617             sub text {
618 18     18 1 1065 my $self = shift();
619              
620 18         26 my %options;
621 18 50       61 if (@_ == 1) {
622             # Deprecated
623 0         0 $options{'prepend'} = shift();
624             }
625             else {
626 18         37 %options = @_;
627             }
628              
629 18         182 my $text = PDF::API2::Content::Text->new();
630              
631 18   33     141 $options{'compress'} //= $self->{' api'}->{'forcecompress'};
632 18 100       79 $text->compressFlate() if $options{'compress'};
633              
634 18 50       49 if ($options{'prepend'}) {
635 0         0 $self->content($text, 1);
636             }
637             else {
638 18         74 $self->content($text);
639             }
640              
641 18         73 return $text;
642             }
643              
644             =head2 object
645              
646             $page = $page->object($object, $x, $y, $scale_x, $scale_y);
647              
648             Places an image or other external object (a.k.a. XObject) on the page in the
649             specified location.
650              
651             If C<$x> and C<$y> are omitted, the object will be placed at C<[0, 0]>.
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 26 my $self = shift();
683              
684 6 100 33     14 unless (exists $self->{'Annots'}) {
685 5         12 $self->{'Annots'} = PDFArray();
686 5         9 $self->{' apipdf'}->out_obj($self);
687             }
688             elsif (ref($self->{'Annots'}) =~ /Objind/) {
689             $self->{'Annots'}->realise();
690             }
691              
692 6         431 require PDF::API2::Annotation;
693 6         33 my $ant = PDF::API2::Annotation->new();
694 6         17 $self->{'Annots'}->add_elements($ant);
695 6         20 $self->{' apipdf'}->new_obj($ant);
696 6         12 $ant->{' apipdf'} = $self->{' apipdf'};
697 6         11 $ant->{' apipage'} = $self;
698 6         12 weaken $ant->{' apipdf'};
699 6         11 weaken $ant->{' apipage'};
700              
701 6 100       16 if ($self->{'Annots'}->is_obj($self->{' apipdf'})) {
702 1         2 $self->{' apipdf'}->out_obj($self->{'Annots'});
703             }
704              
705 6         20 return $ant;
706             }
707              
708             sub resource {
709 29     29 0 100 my ($self, $type, $key, $obj, $force) = @_;
710 29         172 my $dict = $self->find_prop('Resources');
711              
712 29   0     105 $dict = $dict || $self->{'Resources'} || PDFDict();
713              
714 29 50       2481 $dict->realise() if ref($dict) =~ /Objind$/;
715              
716 29   66     194 $dict->{$type} = $dict->{$type} || PDFDict();
717 29 50       140 $dict->{$type}->realise if ref($dict->{$type}) =~ /Objind$/;
718              
719 29 50       118 unless (defined $obj) {
720 0   0       return $dict->{$type}->{$key} || undef;
721             }
722             else {
723 29 50       71 if ($force) {
724 0         0 $dict->{$type}->{$key} = $obj;
725             }
726             else {
727 29   33     207 $dict->{$type}->{$key} = $dict->{$type}->{$key} || $obj;
728             }
729              
730 29 50       243 $self->{' apipdf'}->out_obj($dict) if $dict->is_obj($self->{' apipdf'});
731 29 50       107 $self->{' apipdf'}->out_obj($dict->{$type}) if $dict->{$type}->is_obj($self->{' apipdf'});
732 29 50       102 $self->{' apipdf'}->out_obj($obj) if $obj->is_obj($self->{' apipdf'});
733 29         289 $self->{' apipdf'}->out_obj($self);
734              
735 29         85 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;