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