File Coverage

blib/lib/Renard/Incunabula/Format/PDF/Document.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1 1     1   519366 use Renard::Incunabula::Common::Setup;
  1         3  
  1         7  
2             package Renard::Incunabula::Format::PDF::Document;
3             # ABSTRACT: document that represents a PDF file
4             $Renard::Incunabula::Format::PDF::Document::VERSION = '0.003';
5 1     1   8165 use Moo;
  1         6709  
  1         5  
6 1     1   1584 use Renard::Incunabula::MuPDF::mutool;
  1         79115  
  1         45  
7 1     1   569 use Renard::Incunabula::Format::PDF::Page;
  0            
  0            
8             use Renard::Incunabula::Outline;
9             use Renard::Incunabula::Common::Types qw(PageNumber ZoomLevel);
10              
11             use Math::Trig;
12             use Math::Polygon;
13              
14             use Function::Parameters;
15              
16             extends qw(Renard::Incunabula::Document);
17              
18             has _raw_bounds => (
19             is => 'lazy', # _build_raw_bounds
20             );
21              
22             method _build_last_page_number() :ReturnType(PageNumber) {
23             my $info = Renard::Incunabula::MuPDF::mutool::get_mutool_page_info_xml(
24             $self->filename
25             );
26              
27             return scalar @{ $info->{page} };
28             }
29              
30             method get_rendered_page( (PageNumber) :$page_number, (ZoomLevel) :$zoom_level = 1.0 ) {
31             return Renard::Incunabula::Format::PDF::Page->new(
32             document => $self,
33             page_number => $page_number,
34             zoom_level => $zoom_level,
35             );
36             }
37              
38             method _build_outline() {
39             my $outline_data = Renard::Incunabula::MuPDF::mutool::get_mutool_outline_simple(
40             $self->filename
41             );
42              
43             return Renard::Incunabula::Outline->new( items => $outline_data );
44             }
45              
46             method _build__raw_bounds() {
47             my $info = Renard::Incunabula::MuPDF::mutool::get_mutool_page_info_xml(
48             $self->filename
49             );
50             }
51              
52             method _build_identity_bounds() {
53             my $compute_rotate_dim = sub {
54             my ($info) = @_;
55             my $theta_deg = $info->{rotate} // 0;
56             my $theta_rad = $theta_deg * pi / 180;
57              
58             my ($x, $y) = ($info->{x}, $info->{y});
59             my $poly = Math::Polygon->new(
60             points => [
61             [0, 0],
62             [$x, 0],
63             [$x, $y],
64             [0, $y],
65             ],
66             );
67              
68             my $rotated_poly = $poly->rotate(
69             degrees => $theta_deg,
70             center => [ $x/2, $y/2 ],
71             );
72              
73             my ($xmin, $ymin, $xmax, $ymax) = $rotated_poly->bbox;
74              
75              
76             return { w => $xmax - $xmin, h => $ymax - $ymin };
77             };
78              
79             my $bounds = $self->_raw_bounds;
80             my @page_xy = map {
81             my $p = {
82             x => $_->{MediaBox}{r},
83             y => $_->{MediaBox}{t},
84             rotate => $_->{Rotate}{v} // 0,
85             pageno => $_->{pagenum},
86             };
87             if( exists $p->{rotate} ) {
88             $p->{dims} = $compute_rotate_dim->( $p );
89             }
90              
91             $p;
92             } @{ $bounds->{page} };
93              
94             return \@page_xy;
95             }
96              
97             with qw(
98             Renard::Incunabula::Document::Role::FromFile
99             Renard::Incunabula::Document::Role::Pageable
100             Renard::Incunabula::Document::Role::Renderable
101             Renard::Incunabula::Document::Role::Cacheable
102             Renard::Incunabula::Document::Role::Outlineable
103             Renard::Incunabula::Document::Role::Boundable
104             );
105              
106             1;
107              
108             __END__
109              
110             =pod
111              
112             =encoding UTF-8
113              
114             =head1 NAME
115              
116             Renard::Incunabula::Format::PDF::Document - document that represents a PDF file
117              
118             =head1 VERSION
119              
120             version 0.003
121              
122             =head1 EXTENDS
123              
124             =over 4
125              
126             =item * L<Renard::Incunabula::Document>
127              
128             =back
129              
130             =head1 CONSUMES
131              
132             =over 4
133              
134             =item * L<Renard::Incunabula::Document::Role::Boundable>
135              
136             =item * L<Renard::Incunabula::Document::Role::Cacheable>
137              
138             =item * L<Renard::Incunabula::Document::Role::FromFile>
139              
140             =item * L<Renard::Incunabula::Document::Role::Outlineable>
141              
142             =item * L<Renard::Incunabula::Document::Role::Pageable>
143              
144             =item * L<Renard::Incunabula::Document::Role::Renderable>
145              
146             =back
147              
148             =head1 METHODS
149              
150             =head2 get_rendered_page
151              
152             method get_rendered_page( (PageNumber) :$page_number )
153              
154             See L<Renard::Incunabula::Document::Role::Renderable>.
155              
156             =begin comment
157              
158             =method _build_last_page_number
159              
160             Retrieves the last page number of the PDF. Currently implemented through
161             C<mutool>.
162              
163              
164             =end comment
165              
166             =head1 AUTHOR
167              
168             Project Renard
169              
170             =head1 COPYRIGHT AND LICENSE
171              
172             This software is copyright (c) 2017 by Project Renard.
173              
174             This is free software; you can redistribute it and/or modify it under
175             the same terms as the Perl 5 programming language system itself.
176              
177             =cut