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   1966 use Khonsu::TOC::Outline;
  5         22  
  5         201  
4              
5 5     5   33 use parent 'Khonsu::Text';
  5         7  
  5         24  
6              
7             sub attributes {
8 4     4 0 11 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   21 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   246 level_indent => {$a->RW, $a->NUM, default => sub { 2 }},
21             levels => {$a->RW, $a->HR, default => sub {{
22 4     4   67 h1 => 1,
23             h2 => 2,
24             h3 => 3,
25             h4 => 4,
26             h5 => 5,
27             h6 => 6
28             }}},
29 4         26 );
30             }
31              
32             sub add {
33 4     4 0 33 my ($self, $file, %attributes) = @_;
34 4 100       25 if (!$attributes{x}) {
35 2         12 $attributes{x} = $file->page->x;
36 2         12 $attributes{y} = $file->page->y;
37 2         11 $attributes{h} = $file->page->remaining_height();
38 2         15 $attributes{w} = $file->page->width();
39             }
40 4         38 $self->set_attributes(%attributes);
41 4         34 $self->toc_placeholder({
42             page => $file->page,
43             });
44 4         32 $self->base_outline($file->pdf->outlines()->outline);
45 4         76 $file->onsave('toc', 'render', %attributes);
46 4 50       11 $file->add_page(%{$attributes{page_args} || {}});
  4         47  
47 4         21 return $file;
48             }
49              
50             sub outline {
51 346     346 0 1369 my ($self, $file, $type, %attributes) = @_;
52              
53 346         1398 $self->count($self->count + 1);
54            
55 346   33     1851 $attributes{title} ||= $attributes{text};
56            
57 346         532 delete $attributes{font};
58              
59 346         1228 my $level = $self->levels->{$type};
60              
61 346         1418 my $outline = Khonsu::TOC::Outline->new(
62             page => $file->page,
63             level => $level,
64             %attributes
65             );
66              
67 346 100       1042 if ($level == 1) {
68 59         334 $outline->add($file, $self->base_outline);
69 59         130 push @{ $self->outlines }, $outline;
  59         356  
70             } else {
71 287         1432 $outline->indent($self->level_indent * ($level - 1));
72 287         1299 my $parent = $self->outlines->[-1];
73 287         517 $level--;
74 287         668 while ($level > 1) {
75 570         2063 $parent = $parent->children->[-1];
76 570         1198 $level--;
77             }
78 287         1145 $outline->add($file, $parent->outline);
79 287         459 push @{$parent->children}, $outline;
  287         1373  
80             }
81              
82 346         1272 return $file;
83             }
84              
85             sub render {
86 4     4 0 28 my ($self, $file, %attributes) = @_;
87              
88 4         31 $self->set_attributes(%attributes);
89              
90 4         69 my %position = $self->get_points();
91              
92 4         66 my $page = $self->toc_placeholder->{page};
93              
94 4         27 $file->open_page($self->toc_placeholder->{page}->num());
95              
96 4         26 $file->page->toc(1);
97            
98 4 50       40 if ($self->title) {
99 4         32 $self->SUPER::add($file, text => $self->title, font => $self->title_font_args, %position);
100 4         38 $position{y} += $self->font->size;
101 4 50       47 $position{y} += $self->title_padding if $self->title_padding;
102             }
103              
104 4 50       17 return unless scalar @{$self->outlines};
  4         30  
105              
106 4         33 my $one_toc_link = $self->outlines->[0]->font->size + $self->padding;
107              
108 4         35 $attributes{page_offset} = 0;
109              
110 4         26 my $total_height = ($self->count * $one_toc_link) - $position{h};
111 4 100       38 if ($total_height > 0) {
112 1         4 while ($total_height > 0) {
113 5         10 $attributes{page_offset}++;
114 5         26 $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         6 $file->open_page($self->toc_placeholder->{page}->num());
119             }
120              
121 4         36 %attributes = (%attributes, %position);
122              
123 4         29 my $y = $attributes{y};
124 4         25 my $num = $self->toc_placeholder->{page}->num();
125 4         39 for my $outline (@{$self->outlines}) {
  4         29  
126             $outline->render(
127             $file,
128             %attributes,
129             y => $y,
130             padding => $self->padding,
131 3 50   3   31 num => sub { $_[0] ? ++$num : $num }
132 59         483 );
133 59         842 $y = $outline->end_y + $self->padding;
134 59 50       364 if ($y > $file->page->h - ($file->page->footer ? $file->page->footer->h : 0)) {
    100          
135 2         6 $num++;
136 2         15 $file->open_page($num);
137 2 50       9 $y = $file->page->header ? $file->page->header->h : 0;
138             }
139             }
140              
141 4         112 $file->page_offset($attributes{page_offset});
142              
143 4         52 return $file;
144             }
145              
146             1;