File Coverage

blib/lib/Khonsu/TOC.pm
Criterion Covered Total %
statement 79 79 100.0
branch 15 22 68.1
condition 1 3 33.3
subroutine 10 10 100.0
pod 0 4 0.0
total 105 118 88.9


line stmt bran cond sub pod time code
1             package Khonsu::TOC;
2              
3 5     5   1951 use Khonsu::TOC::Outline;
  5         16  
  5         160  
4              
5 5     5   32 use parent 'Khonsu::Text';
  5         10  
  5         22  
6              
7             sub attributes {
8 4     4 0 13 my $a = shift;
9             return (
10             $a->SUPER::attributes(),
11             title => {$a->RW, $a->STR},
12             title_font_args => {$a->RW, $a->HR},
13             title_padding => {$a->RW, $a->NUM},
14             font_args => {$a->RW, $a->HR},
15 4     4   23 padding => {$a->RW, $a->NUM, default => sub { 0 }},
16             count => {$a->RW, $a->NUM},
17             toc_placeholder => {$a->RW, $a->HR},
18             base_outline => {$a->RW, $a->OBJ},
19             outlines => {$a->RW, $a->DAR},
20 4     4   210 level_indent => {$a->RW, $a->NUM, default => sub { 2 }},
21             levels => {$a->RW, $a->HR, default => sub {{
22 4     4   50 h1 => 1,
23             h2 => 2,
24             h3 => 3,
25             h4 => 4,
26             h5 => 5,
27             h6 => 6
28             }}},
29 4         21 );
30             }
31              
32             sub add {
33 4     4 0 22 my ($self, $file, %attributes) = @_;
34 4 100       23 if (!$attributes{x}) {
35 2         11 $attributes{x} = $file->page->x;
36 2         18 $attributes{y} = $file->page->y;
37 2         11 $attributes{h} = $file->page->remaining_height();
38 2         14 $attributes{w} = $file->page->width();
39             }
40 4         51 $self->set_attributes(%attributes);
41 4         37 $self->toc_placeholder({
42             page => $file->page,
43             });
44 4         24 $self->base_outline($file->pdf->outlines()->outline);
45 4         73 $file->onsave('toc', 'render', %attributes);
46 4 50       11 $file->add_page(%{$attributes{page_args} || {}});
  4         45  
47 4         19 return $file;
48             }
49              
50             sub outline {
51 346     346 0 1240 my ($self, $file, $type, %attributes) = @_;
52              
53 346         1374 $self->count($self->count + 1);
54            
55 346   33     1680 $attributes{title} ||= $attributes{text};
56            
57 346         596 delete $attributes{font};
58              
59 346         1217 my $level = $self->levels->{$type};
60              
61 346         1401 my $outline = Khonsu::TOC::Outline->new(
62             page => $file->page,
63             level => $level,
64             %attributes
65             );
66              
67 346 100       1076 if ($level == 1) {
68 59         328 $outline->add($file, $self->base_outline);
69 59         112 push @{ $self->outlines }, $outline;
  59         300  
70             } else {
71 287         1521 $outline->indent($self->level_indent * ($level - 1));
72 287         1272 my $parent = $self->outlines->[-1];
73 287         516 $level--;
74 287         644 while ($level > 1) {
75 570         2077 $parent = $parent->children->[-1];
76 570         1246 $level--;
77             }
78 287         1088 $outline->add($file, $parent->outline);
79 287         442 push @{$parent->children}, $outline;
  287         1243  
80             }
81              
82 346         1282 return $file;
83             }
84              
85             sub render {
86 4     4 0 26 my ($self, $file, %attributes) = @_;
87              
88 4         32 $self->set_attributes(%attributes);
89              
90 4         43 my %position = $self->get_points();
91              
92 4         26 my $page = $self->toc_placeholder->{page};
93              
94 4         24 $file->open_page($self->toc_placeholder->{page}->num());
95              
96 4         24 $file->page->toc(1);
97            
98 4 50       37 if ($self->title) {
99 4         26 $self->SUPER::add($file, text => $self->title, font => $self->title_font_args, %position);
100 4         31 $position{y} += $self->font->size;
101 4 50       51 $position{y} += $self->title_padding if $self->title_padding;
102             }
103              
104 4 50       19 return unless scalar @{$self->outlines};
  4         24  
105              
106 4         23 my $one_toc_link = $self->outlines->[0]->font->size + $self->padding;
107              
108 4         20 $attributes{page_offset} = 0;
109              
110 4         25 my $total_height = ($self->count * $one_toc_link) - $position{h};
111 4 100       53 if ($total_height > 0) {
112 1         3 while ($total_height > 0) {
113 5         10 $attributes{page_offset}++;
114 5         23 $file->add_page(toc => 1, num => $self->toc_placeholder->{page}->num() + $attributes{page_offset});
115 5         24 $total_height -= $file->page->h;
116             }
117              
118 1         7 $file->open_page($self->toc_placeholder->{page}->num());
119             }
120              
121 4         36 %attributes = (%attributes, %position);
122              
123 4         17 my $y = $attributes{y};
124 4         23 my $num = $self->toc_placeholder->{page}->num();
125 4         14 for my $outline (@{$self->outlines}) {
  4         20  
126             $outline->render(
127             $file,
128             %attributes,
129             y => $y,
130             padding => $self->padding,
131 3 50   3   28 num => sub { $_[0] ? ++$num : $num }
132 59         481 );
133 59         772 $y = $outline->end_y + $self->padding;
134 59 50       413 if ($y > $file->page->h - ($file->page->footer ? $file->page->footer->h : 0)) {
    100          
135 2         20 $num++;
136 2         46 $file->open_page($num);
137 2 50       13 $y = $file->page->header ? $file->page->header->h : 0;
138             }
139             }
140              
141 4         60 $file->page_offset($attributes{page_offset});
142              
143 4         41 return $file;
144             }
145              
146             1;