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   1926 use Khonsu::TOC::Outline;
  5         17  
  5         168  
4              
5 5     5   29 use parent 'Khonsu::Text';
  5         10  
  5         19  
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   13 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   218 level_indent => {$a->RW, $a->NUM, default => sub { 2 }},
21             levels => {$a->RW, $a->HR, default => sub {{
22 4     4   31 h1 => 1,
23             h2 => 2,
24             h3 => 3,
25             h4 => 4,
26             h5 => 5,
27             h6 => 6
28             }}},
29 4         22 );
30             }
31              
32             sub add {
33 4     4 0 20 my ($self, $file, %attributes) = @_;
34 4 100       21 if (!$attributes{x}) {
35 2         13 $attributes{x} = $file->page->x;
36 2         26 $attributes{y} = $file->page->y;
37 2         23 $attributes{h} = $file->page->remaining_height();
38 2         13 $attributes{w} = $file->page->width();
39             }
40 4         40 $self->set_attributes(%attributes);
41 4         29 $self->toc_placeholder({
42             page => $file->page,
43             });
44 4         29 $self->base_outline($file->pdf->outlines()->outline);
45 4         64 $file->onsave('toc', 'render', %attributes);
46 4 50       10 $file->add_page(%{$attributes{page_args} || {}});
  4         44  
47 4         16 return $file;
48             }
49              
50             sub outline {
51 346     346 0 1339 my ($self, $file, $type, %attributes) = @_;
52              
53 346         1364 $self->count($self->count + 1);
54            
55 346   33     1806 $attributes{title} ||= $attributes{text};
56            
57 346         523 delete $attributes{font};
58              
59 346         1244 my $level = $self->levels->{$type};
60              
61 346         1276 my $outline = Khonsu::TOC::Outline->new(
62             page => $file->page,
63             level => $level,
64             %attributes
65             );
66              
67 346 100       1044 if ($level == 1) {
68 59         355 $outline->add($file, $self->base_outline);
69 59         127 push @{ $self->outlines }, $outline;
  59         282  
70             } else {
71 287         1411 $outline->indent($self->level_indent * ($level - 1));
72 287         1273 my $parent = $self->outlines->[-1];
73 287         508 $level--;
74 287         688 while ($level > 1) {
75 570         2040 $parent = $parent->children->[-1];
76 570         1203 $level--;
77             }
78 287         1068 $outline->add($file, $parent->outline);
79 287         466 push @{$parent->children}, $outline;
  287         1149  
80             }
81              
82 346         1370 return $file;
83             }
84              
85             sub render {
86 4     4 0 28 my ($self, $file, %attributes) = @_;
87              
88 4         29 $self->set_attributes(%attributes);
89              
90 4         53 my %position = $self->get_points();
91              
92 4         47 my $page = $self->toc_placeholder->{page};
93              
94 4         24 $file->open_page($self->toc_placeholder->{page}->num());
95              
96 4         26 $file->page->toc(1);
97            
98 4 50       36 if ($self->title) {
99 4         28 $self->SUPER::add($file, text => $self->title, font => $self->title_font_args, %position);
100 4         30 $position{y} += $self->font->size;
101 4 50       51 $position{y} += $self->title_padding if $self->title_padding;
102             }
103              
104 4 50       18 return unless scalar @{$self->outlines};
  4         23  
105              
106 4         24 my $one_toc_link = $self->outlines->[0]->font->size + $self->padding;
107              
108 4         16 $attributes{page_offset} = 0;
109              
110 4         26 my $total_height = ($self->count * $one_toc_link) - $position{h};
111 4 100       23 if ($total_height > 0) {
112 1         6 while ($total_height > 0) {
113 5         11 $attributes{page_offset}++;
114 5         22 $file->add_page(toc => 1, num => $self->toc_placeholder->{page}->num() + $attributes{page_offset});
115 5         26 $total_height -= $file->page->h;
116             }
117              
118 1         11 $file->open_page($self->toc_placeholder->{page}->num());
119             }
120              
121 4         31 %attributes = (%attributes, %position);
122              
123 4         18 my $y = $attributes{y};
124 4         26 my $num = $self->toc_placeholder->{page}->num();
125 4         21 for my $outline (@{$self->outlines}) {
  4         32  
126             $outline->render(
127             $file,
128             %attributes,
129             y => $y,
130             padding => $self->padding,
131 3 50   3   33 num => sub { $_[0] ? ++$num : $num }
132 59         493 );
133 59         884 $y = $outline->end_y + $self->padding;
134 59 50       346 if ($y > $file->page->h - ($file->page->footer ? $file->page->footer->h : 0)) {
    100          
135 2         13 $num++;
136 2         31 $file->open_page($num);
137 2 50       11 $y = $file->page->header ? $file->page->header->h : 0;
138             }
139             }
140              
141 4         79 $file->page_offset($attributes{page_offset});
142              
143 4         49 return $file;
144             }
145              
146             1;