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 39     39   300 use base 'PDF::API2::Basic::PDF::Pages';
  39         84  
  39         4614  
4              
5 39     39   275 use strict;
  39         87  
  39         888  
6 39     39   287 use warnings;
  39         111  
  39         1975  
7              
8             our $VERSION = '2.045'; # VERSION
9              
10 39     39   264 use Carp;
  39         92  
  39         2995  
11 39     39   316 use POSIX qw(floor);
  39         87  
  39         230  
12 39     39   2841 use Scalar::Util qw(looks_like_number weaken);
  39         113  
  39         1813  
13              
14 39     39   229 use PDF::API2::Basic::PDF::Utils;
  39         77  
  39         2447  
15 39     39   25327 use PDF::API2::Content;
  39         118  
  39         1631  
16 39     39   16762 use PDF::API2::Content::Text;
  39         118  
  39         1166  
17 39     39   255 use PDF::API2::Util;
  39         86  
  39         113740  
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 396 my ($class, $pdf, $parent, $index) = @_;
80 142         282 my $self = {};
81              
82 142 50       409 $class = ref($class) if ref($class);
83 142         583 $self = $class->SUPER::new($pdf, $parent);
84 142         400 $self->{'Type'} = PDFName('Page');
85 142         595 $self->proc_set(qw( PDF Text ImageB ImageC ImageI ));
86 142         471 delete $self->{'Count'};
87 142         333 delete $self->{'Kids'};
88 142         561 $parent->add_page($self, $index);
89 142         404 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 2071 my $self = shift();
144              
145             # Set
146 1 50       4 if (@_) {
147 1         4 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   9 my $value = shift();
293              
294             # An array of two or four numbers in points
295 6 50       11 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       21 if ($value =~ /^([0-9.]+)\s*x\s*([0-9.]+)$/) {
307 2         7 my ($w, $h) = ($1, $2);
308 2 50 33     14 if (looks_like_number($w) and looks_like_number($h)) {
309 2         7 return (0, 0, $w * 72, $h * 72);
310             }
311             }
312              
313             # Common names for page sizes
314 4 50       12 if ($page_sizes->{lc $value}) {
315 4         7 return (0, 0, @{$page_sizes->{lc $value}});
  4         11  
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 4200 my $self = shift();
328              
329             # Get
330 6 50 33     19 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         15 my %boxes = @_;
345 6         9 foreach my $box (qw(media crop bleed trim art)) {
346 30 100       53 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         12 my $value = $boxes{$box};
353 8         9 my @rectangle;
354 8 100 66     28 if ($box ne 'media' and not ref($value) and looks_like_number($value)) {
      66        
355 2 50       9 my $parent = ($box eq 'crop' ? 'media' :
    50          
    50          
356             $box eq 'bleed' ? 'media' :
357             $box eq 'trim' ? 'bleed' : 'trim');
358 2 50 33     7 $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     4 $parent = 'media' if $parent eq 'bleed' and not $boxes{'bleed'};
361 2 50       5 unless ($boxes{$parent}) {
362 0         0 croak "Single-number argument for $box requires $parent";
363             }
364              
365 2         3 @rectangle = @{$boxes{$parent}};
  2         4  
366 2         4 $rectangle[0] += $value;
367 2         2 $rectangle[1] += $value;
368 2         3 $rectangle[2] -= $value;
369 2         3 $rectangle[3] -= $value;
370             }
371             else {
372 6         10 @rectangle = _to_rectangle($value);
373             }
374              
375 8         20 my $box_name = ucfirst($box) . 'Box';
376 8         19 $self->_bounding_box($box_name, @rectangle);
377 8         33 $boxes{$box} = [@rectangle];
378             }
379              
380 6         15 return $self;
381             }
382              
383             sub _bounding_box {
384 92     92   2326 my $self = shift();
385 92         106 my $type = shift();
386              
387             # Get
388 92 100       165 unless (scalar @_) {
389 46         113 my $box = $self->find_prop($type);
390 46 50       95 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         101 return map { $_->val() } $box->elements();
  184         284  
400             }
401              
402             # Set
403 46         100 $self->{$type} = PDFArray(map { PDFNum(float($_)) } page_size(@_));
  184         319  
404 46         101 return $self;
405             }
406              
407             # Deprecated; use size(...) or boundaries('media', ...)
408             sub mediabox {
409 38     38 1 67648 my $self = shift();
410 38 50       101 return $self->_bounding_box('MediaBox') unless @_;
411 38         115 return $self->_bounding_box('MediaBox', page_size(@_));
412             }
413              
414             # Deprecated
415             sub get_mediabox {
416 34     34 1 129 my $self = shift();
417 34         45 return $self->_bounding_box('MediaBox');
418             }
419              
420             # Deprecated; use boundaries('crop', ...)
421             sub cropbox {
422 1     1 1 2097 my $self = shift();
423 1 50       4 return $self->_bounding_box('CropBox') unless @_;
424 1         5 return $self->_bounding_box('CropBox', page_size(@_));
425             }
426              
427             # Deprecated
428             sub get_cropbox {
429 2     2 1 8 my $self = shift();
430 2         5 return $self->_bounding_box('CropBox');
431             }
432              
433             # Deprecated; use boundaries('bleed', ...)
434             sub bleedbox {
435 1     1 1 2105 my $self = shift();
436 1 50       5 return $self->_bounding_box('BleedBox') unless @_;
437 1         4 return $self->_bounding_box('BleedBox', page_size(@_));
438             }
439              
440             # Deprecated
441             sub get_bleedbox {
442 2     2 1 7 my $self = shift();
443 2         5 return $self->_bounding_box('BleedBox');
444             }
445              
446             # Deprecated; use boundaries('trim', ...)
447             sub trimbox {
448 1     1 1 2016 my $self = shift();
449 1 50       4 return $self->_bounding_box('TrimBox') unless @_;
450 1         4 return $self->_bounding_box('TrimBox', page_size(@_));
451             }
452              
453             # Deprecated
454             sub get_trimbox {
455 2     2 1 9 my $self = shift();
456 2         5 return $self->_bounding_box('TrimBox');
457             }
458              
459             # Deprecated; use boundaries('art', ...)
460             sub artbox {
461 1     1 1 2176 my $self = shift();
462 1 50       5 return $self->_bounding_box('ArtBox') unless @_;
463 1         4 return $self->_bounding_box('ArtBox', page_size(@_));
464             }
465              
466             # Deprecated
467             sub get_artbox {
468 2     2 1 10 my $self = shift();
469 2         5 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 210 my $self = shift();
536 128   66     515 $self->{'Contents'} = $self->{'Contents'} || PDFArray();
537 128 50       505 if (ref($self->{'Contents'}) =~ /Objind$/) {
538 0         0 $self->{'Contents'}->realise();
539             }
540 128 50       605 if (ref($self->{'Contents'}) !~ /Array$/) {
541 0         0 $self->{'Contents'} = PDFArray($self->{'Contents'});
542             }
543 128         234 return;
544             }
545              
546             sub content {
547 122     122 0 284 my ($self, $obj, $dir) = @_;
548 122 50 33     366 if (defined($dir) and $dir > 0) {
549 0         0 $self->precontent($obj);
550             }
551             else {
552 122         314 $self->addcontent($obj);
553             }
554 122 50       2149 $self->{' apipdf'}->new_obj($obj) unless $obj->is_obj($self->{' apipdf'});
555 122         285 $obj->{' apipdf'} = $self->{' apipdf'};
556 122         263 $obj->{' api'} = $self->{' api'};
557 122         231 $obj->{' apipage'} = $self;
558              
559 122         440 weaken $obj->{' apipdf'};
560 122         304 weaken $obj->{' api'};
561 122         355 weaken $obj->{' apipage'};
562              
563 122         438 return $obj;
564             }
565              
566             sub addcontent {
567 122     122 0 255 my ($self, @objs) = @_;
568 122         350 $self->fixcontents();
569 122         378 $self->{'Contents'}->add_elements(@objs);
570 122         207 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 521 my ($self, $prepend) = @_;
583 52         141 my $graphics = $self->graphics(prepend => $prepend);
584              
585             # Delete the input validation flag
586 52         96 delete $graphics->{' graphics'};
587              
588 52         216 return $graphics;
589             }
590              
591             sub graphics {
592 104     104 1 271 my ($self, %options) = @_;
593 104         575 my $graphics = PDF::API2::Content->new();
594 104         202 $graphics->{' graphics'} = 1;
595              
596 104   66     523 $options{'compress'} //= $self->{' api'}->{'forcecompress'};
597 104 100       301 $graphics->compressFlate() if $options{'compress'};
598              
599 104 50       232 if ($options{'prepend'}) {
600 0         0 return $self->content($graphics, 1);
601             }
602             else {
603 104         327 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 1077 my $self = shift();
619              
620 18         32 my %options;
621 18 50       53 if (@_ == 1) {
622             # Deprecated
623 0         0 $options{'prepend'} = shift();
624             }
625             else {
626 18         61 %options = @_;
627             }
628              
629 18         146 my $text = PDF::API2::Content::Text->new();
630              
631 18   66     134 $options{'compress'} //= $self->{' api'}->{'forcecompress'};
632 18 100       75 $text->compressFlate() if $options{'compress'};
633              
634 18 50       59 if ($options{'prepend'}) {
635 0         0 $self->content($text, 1);
636             }
637             else {
638 18         59 $self->content($text);
639             }
640              
641 18         81 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 34 my $self = shift();
683              
684 6 100 33     21 unless (exists $self->{'Annots'}) {
685 5         13 $self->{'Annots'} = PDFArray();
686 5         14 $self->{' apipdf'}->out_obj($self);
687             }
688             elsif (ref($self->{'Annots'}) =~ /Objind/) {
689             $self->{'Annots'}->realise();
690             }
691              
692 6         509 require PDF::API2::Annotation;
693 6         32 my $ant = PDF::API2::Annotation->new();
694 6         21 $self->{'Annots'}->add_elements($ant);
695 6         20 $self->{' apipdf'}->new_obj($ant);
696 6         18 $ant->{' apipdf'} = $self->{' apipdf'};
697 6         14 $ant->{' apipage'} = $self;
698 6         20 weaken $ant->{' apipdf'};
699 6         15 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         26 return $ant;
706             }
707              
708             sub resource {
709 29     29 0 115 my ($self, $type, $key, $obj, $force) = @_;
710 29         118 my $dict = $self->find_prop('Resources');
711              
712 29   0     103 $dict = $dict || $self->{'Resources'} || PDFDict();
713              
714 29 50       175 $dict->realise() if ref($dict) =~ /Objind$/;
715              
716 29   66     170 $dict->{$type} = $dict->{$type} || PDFDict();
717 29 50       137 $dict->{$type}->realise if ref($dict->{$type}) =~ /Objind$/;
718              
719 29 50       95 unless (defined $obj) {
720 0   0       return $dict->{$type}->{$key} || undef;
721             }
722             else {
723 29 50       80 if ($force) {
724 0         0 $dict->{$type}->{$key} = $obj;
725             }
726             else {
727 29   33     195 $dict->{$type}->{$key} = $dict->{$type}->{$key} || $obj;
728             }
729              
730 29 50       129 $self->{' apipdf'}->out_obj($dict) if $dict->is_obj($self->{' apipdf'});
731 29 50       124 $self->{' apipdf'}->out_obj($dict->{$type}) if $dict->{$type}->is_obj($self->{' apipdf'});
732 29 50       113 $self->{' apipdf'}->out_obj($obj) if $obj->is_obj($self->{' apipdf'});
733 29         114 $self->{' apipdf'}->out_obj($self);
734              
735 29         243 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;