line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package PDF::Collage::Template; |
2
|
2
|
|
|
2
|
|
26
|
use v5.24; |
|
2
|
|
|
|
|
6
|
|
3
|
2
|
|
|
2
|
|
11
|
use warnings; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
85
|
|
4
|
|
|
|
|
|
|
{ our $VERSION = '0.001' } |
5
|
|
|
|
|
|
|
|
6
|
2
|
|
|
2
|
|
11
|
use Carp; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
119
|
|
7
|
2
|
|
|
2
|
|
1045
|
use Template::Perlish (); |
|
2
|
|
|
|
|
7955
|
|
|
2
|
|
|
|
|
47
|
|
8
|
2
|
|
|
2
|
|
13
|
use Data::Resolver (); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
31
|
|
9
|
2
|
|
|
2
|
|
2208
|
use PDF::Builder; |
|
2
|
|
|
|
|
569469
|
|
|
2
|
|
|
|
|
94
|
|
10
|
|
|
|
|
|
|
|
11
|
2
|
|
|
2
|
|
1177
|
use Moo; |
|
2
|
|
|
|
|
16160
|
|
|
2
|
|
|
|
|
19
|
|
12
|
2
|
|
|
2
|
|
3015
|
use experimental qw< signatures >; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
17
|
|
13
|
2
|
|
|
2
|
|
354
|
no warnings qw< experimental::signatures >; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
69
|
|
14
|
|
|
|
|
|
|
|
15
|
2
|
|
|
2
|
|
1018
|
use namespace::clean; |
|
2
|
|
|
|
|
30062
|
|
|
2
|
|
|
|
|
13
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
has commands => (is => ro => required => 1); |
18
|
|
|
|
|
|
|
has functions => (is => 'lazy'); |
19
|
|
|
|
|
|
|
has logger => (is => 'lazy'); |
20
|
|
|
|
|
|
|
has metadata => (is => 'lazy'); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
has _data => (is => 'lazy'); |
23
|
|
|
|
|
|
|
has _defaults => (is => 'lazy'); |
24
|
|
|
|
|
|
|
has _fonts => (is => 'lazy'); |
25
|
|
|
|
|
|
|
has _pdf => (is => 'lazy'); |
26
|
|
|
|
|
|
|
|
27
|
0
|
|
|
0
|
|
0
|
sub _build_functions ($self) { return {} } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
28
|
0
|
|
|
0
|
|
0
|
sub _build_logger ($self) { |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
29
|
0
|
|
|
|
|
0
|
eval { require Log::Any; Log::Any->get_logger } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
30
|
|
|
|
|
|
|
} |
31
|
0
|
|
|
0
|
|
0
|
sub _build_metadata ($self) { return {} } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
32
|
0
|
|
|
0
|
|
0
|
sub _build__data ($self) { return {} } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
33
|
17
|
|
|
17
|
|
245
|
sub _build__defaults ($self) { return {} } |
|
17
|
|
|
|
|
29
|
|
|
17
|
|
|
|
|
35
|
|
|
17
|
|
|
|
|
69
|
|
34
|
16
|
|
|
16
|
|
257
|
sub _build__fonts ($self) { return {} } |
|
16
|
|
|
|
|
27
|
|
|
16
|
|
|
|
|
25
|
|
|
16
|
|
|
|
|
373
|
|
35
|
16
|
|
|
16
|
|
193
|
sub _build__pdf ($self) { return PDF::Builder->new } |
|
16
|
|
|
|
|
47
|
|
|
16
|
|
|
|
|
28
|
|
|
16
|
|
|
|
|
121
|
|
36
|
|
|
|
|
|
|
|
37
|
17
|
|
|
17
|
1
|
4509
|
sub render ($self, $data) { |
|
17
|
|
|
|
|
44
|
|
|
17
|
|
|
|
|
40
|
|
|
17
|
|
|
|
|
42
|
|
38
|
17
|
|
|
|
|
398
|
$self->new( # hand over to a disposable clone |
39
|
|
|
|
|
|
|
commands => $self->commands, |
40
|
|
|
|
|
|
|
functions => $self->functions, |
41
|
|
|
|
|
|
|
_data => $data, |
42
|
|
|
|
|
|
|
)->_real_render; |
43
|
|
|
|
|
|
|
} ## end sub render |
44
|
|
|
|
|
|
|
|
45
|
17
|
|
|
17
|
|
1001
|
sub _real_render ($self) { |
|
17
|
|
|
|
|
32
|
|
|
17
|
|
|
|
|
29
|
|
46
|
17
|
|
|
|
|
63
|
for my $command ($self->commands->@*) { |
47
|
66
|
|
|
|
|
300394
|
my $op = $command->{op} =~ s{-}{_}rgmxs; |
48
|
66
|
50
|
|
|
|
502
|
my $method = $self->can('_op_' . $op) |
49
|
|
|
|
|
|
|
or croak "unsupported op<$command->{op}>"; |
50
|
66
|
|
|
|
|
273
|
$self->$method($command); |
51
|
|
|
|
|
|
|
} ## end for my $command ($self->...) |
52
|
16
|
|
|
|
|
470
|
return $self->_pdf; |
53
|
|
|
|
|
|
|
} ## end sub _real_render |
54
|
|
|
|
|
|
|
|
55
|
194
|
|
|
194
|
|
284
|
sub _tpr ($self, $tmpl) { |
|
194
|
|
|
|
|
296
|
|
|
194
|
|
|
|
|
279
|
|
|
194
|
|
|
|
|
286
|
|
56
|
194
|
|
|
|
|
4252
|
return Template::Perlish::render($tmpl, $self->_data, |
57
|
|
|
|
|
|
|
{functions => $self->functions}); |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
49
|
|
|
49
|
|
108
|
sub _expand ($self, $command, @keys) { |
|
49
|
|
|
|
|
85
|
|
|
49
|
|
|
|
|
80
|
|
|
49
|
|
|
|
|
169
|
|
|
49
|
|
|
|
|
65
|
|
61
|
49
|
|
|
|
|
114
|
my %auto_expand = map { $_ => 1 } @keys; |
|
260
|
|
|
|
|
620
|
|
62
|
49
|
|
|
|
|
1264
|
my %overall = ($self->_defaults->%*, $command->%*); |
63
|
49
|
|
|
|
|
852
|
my %retval; |
64
|
49
|
|
|
|
|
279
|
for my $key (sort { $a cmp $b } keys %overall) { |
|
547
|
|
|
|
|
837
|
|
65
|
309
|
|
|
|
|
125456
|
my $nkey = $key =~ s{-}{_}rgmxs; |
66
|
309
|
50
|
|
|
|
792
|
next if exists $retval{$nkey}; |
67
|
309
|
|
|
|
|
518
|
my $value = $overall{$key}; |
68
|
309
|
100
|
|
|
|
1036
|
$retval{$nkey} = $auto_expand{$nkey} ? $self->_tpr($value) : $value; |
69
|
|
|
|
|
|
|
} ## end for my $key (sort { $a ...}) |
70
|
49
|
|
|
|
|
38606
|
return \%retval; |
71
|
|
|
|
|
|
|
} ## end sub _expand |
72
|
65
|
100
|
|
65
|
|
609
|
sub __pageno ($input) { return $input eq 'last' ? 0 : $input } |
|
65
|
|
|
|
|
123
|
|
|
65
|
|
|
|
|
101
|
|
|
65
|
|
|
|
|
328
|
|
73
|
16
|
|
33
|
16
|
|
45
|
sub _font ($s, $key) { $s->_fonts->{$key} //= $s->_pdf->font($key) } |
|
16
|
|
|
|
|
43
|
|
|
16
|
|
|
|
|
39
|
|
|
16
|
|
|
|
|
26
|
|
|
16
|
|
|
|
|
438
|
|
74
|
|
|
|
|
|
|
|
75
|
16
|
|
|
16
|
|
52
|
sub _op_add_image ($self, $command) { |
|
16
|
|
|
|
|
39
|
|
|
16
|
|
|
|
|
32
|
|
|
16
|
|
|
|
|
31
|
|
76
|
16
|
|
|
|
|
72
|
my $opts = $self->_expand($command, qw< page path x y width height >); |
77
|
16
|
|
50
|
|
|
387
|
my $page = $self->_pdf->open_page(__pageno($opts->{page} // 'last')); |
78
|
16
|
|
|
|
|
1337
|
my $image = $self->_pdf->image($opts->{path}); |
79
|
16
|
|
|
|
|
543992
|
$page->object($image, $opts->@{qw< x y width height >}); |
80
|
16
|
|
|
|
|
11828
|
return; |
81
|
|
|
|
|
|
|
} ## end sub _op_add_image |
82
|
|
|
|
|
|
|
|
83
|
17
|
|
|
17
|
|
30
|
sub _op_add_page ($self, $command) { |
|
17
|
|
|
|
|
21
|
|
|
17
|
|
|
|
|
37
|
|
|
17
|
|
|
|
|
20
|
|
84
|
17
|
|
|
|
|
63
|
my $opts = |
85
|
|
|
|
|
|
|
$self->_expand($command, qw< page from from_path from_page >); |
86
|
17
|
|
50
|
|
|
198
|
my $target_n = __pageno($opts->{page} // 'last'); |
87
|
|
|
|
|
|
|
defined(my $source_path = $opts->{from} // $opts->{from_path}) |
88
|
17
|
50
|
33
|
|
|
97
|
or return $self->_pdf->page($target_n); |
89
|
17
|
|
|
|
|
141
|
my $source = PDF::Builder->open($source_path); |
90
|
16
|
|
50
|
|
|
150039
|
my $source_n = __pageno($opts->{from_page} // 'last'); |
91
|
16
|
|
|
|
|
421
|
return $self->_pdf->import_page($source, $source_n, $target_n); |
92
|
|
|
|
|
|
|
} ## end sub _op_add_page |
93
|
|
|
|
|
|
|
|
94
|
16
|
|
|
16
|
|
46
|
sub _op_add_text ($self, $command) { |
|
16
|
|
|
|
|
39
|
|
|
16
|
|
|
|
|
36
|
|
|
16
|
|
|
|
|
33
|
|
95
|
16
|
|
|
|
|
78
|
my $opts = |
96
|
|
|
|
|
|
|
$self->_expand($command, qw< page font font_family font_size x y >); |
97
|
16
|
|
50
|
|
|
384
|
my $page = $self->_pdf->open_page(__pageno($opts->{page} // 'last')); |
98
|
16
|
|
|
|
|
786
|
my $text = $page->text; |
99
|
|
|
|
|
|
|
|
100
|
16
|
|
33
|
|
|
5310
|
my $font = $self->_font($opts->{font} // $opts->{font_family}); |
101
|
16
|
|
|
|
|
762948
|
$text->font($font, $opts->{font_size}); |
102
|
|
|
|
|
|
|
|
103
|
16
|
|
50
|
|
|
4522
|
$text->position(map { $_ // 0 } $opts->@{qw< x y >}); |
|
32
|
|
|
|
|
173
|
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
my $content = |
106
|
16
|
|
|
|
|
1847
|
$self->_render_text($opts->@{qw< text text_template text_var >}); |
107
|
16
|
|
50
|
|
|
27218
|
$text->text($content // ''); |
108
|
|
|
|
|
|
|
|
109
|
16
|
|
|
|
|
257500
|
return $self; |
110
|
|
|
|
|
|
|
} ## end sub _op_add_text |
111
|
|
|
|
|
|
|
|
112
|
16
|
|
|
16
|
|
46
|
sub _render_text ($self, $plain, $template, $crumbs) { |
|
16
|
|
|
|
|
40
|
|
|
16
|
|
|
|
|
29
|
|
|
16
|
|
|
|
|
36
|
|
|
16
|
|
|
|
|
37
|
|
|
16
|
|
|
|
|
27
|
|
113
|
16
|
50
|
|
|
|
50
|
return $plain if defined $plain; |
114
|
16
|
50
|
|
|
|
83
|
return $self->_tpr($template) if defined $template; |
115
|
0
|
0
|
0
|
|
|
0
|
return Template::Perlish::traverse($self->_data, $crumbs) // '' |
116
|
|
|
|
|
|
|
if defined $crumbs; |
117
|
0
|
|
|
|
|
0
|
return; |
118
|
|
|
|
|
|
|
} ## end sub _render_text |
119
|
|
|
|
|
|
|
|
120
|
17
|
|
|
17
|
|
42
|
sub _op_set_defaults ($self, $command) { |
|
17
|
|
|
|
|
29
|
|
|
17
|
|
|
|
|
24
|
|
|
17
|
|
|
|
|
26
|
|
121
|
17
|
|
|
|
|
371
|
my $defaults = $self->_defaults; |
122
|
17
|
|
|
|
|
99
|
while (my ($key, $value) = each $command->%*) { |
123
|
51
|
100
|
|
|
|
145
|
next if $key eq 'op'; |
124
|
34
|
50
|
|
|
|
75
|
if (defined $value) { $defaults->{$key} = $value } |
|
34
|
|
|
|
|
124
|
|
125
|
0
|
|
|
|
|
0
|
else { delete $defaults->{$key} } |
126
|
|
|
|
|
|
|
} |
127
|
17
|
|
|
|
|
54
|
return; |
128
|
|
|
|
|
|
|
} ## end sub _op_set_defaults |
129
|
|
|
|
|
|
|
|
130
|
0
|
|
|
0
|
|
|
sub _default_log ($self, $command) { |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
131
|
0
|
|
|
|
|
|
warn "[$command->{level}] $command->{message}\n"; |
132
|
0
|
|
|
|
|
|
return $self; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
0
|
|
|
0
|
|
|
sub _op_log ($self, $command) { |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
136
|
0
|
0
|
|
|
|
|
my $logger = $self->logger or return $self->_default_log($command); |
137
|
0
|
0
|
0
|
|
|
|
my $method = $logger->can(lc($command->{level}) // 'info') |
138
|
|
|
|
|
|
|
or return $self->_default_log($command); |
139
|
0
|
|
|
|
|
|
$logger->$method($command->{message}); |
140
|
0
|
|
|
|
|
|
return $self; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
1; |