our
$VERSION
=
'3.026'
;
our
$LAST_UPDATE
=
'3.026'
;
our
%inst
=
map
{
$_
=> 1}
qw(Parent Type)
;
sub
new {
my
(
$class
,
$pdf
,
$parent
) =
@_
;
$pdf
//=
$class
->get_top()->{
' parent'
}
if
ref
(
$class
);
if
(
ref
(
$pdf
) eq
'ARRAY'
) {
die
'Pages: Only one PDF is supported as of version 3.016'
if
scalar
(
@$pdf
) > 1;
(
$pdf
) =
@$pdf
;
}
$class
=
ref
(
$class
)
if
ref
(
$class
);
my
$self
=
$class
->SUPER::new(
$pdf
,
$parent
);
$self
->{
'Type'
} = PDFName(
'Pages'
);
$self
->{
'Parent'
} =
$parent
if
defined
$parent
;
$self
->{
'Count'
} = PDFNum(0);
$self
->{
'Kids'
} = PDF::Builder::Basic::PDF::Array->new();
$pdf
->new_obj(
$self
);
unless
(
defined
$self
->{
'Parent'
}) {
$pdf
->{
'Root'
}->{
'Pages'
} =
$self
;
$pdf
->out_obj(
$pdf
->{
'Root'
});
$self
->{
' parent'
} =
$pdf
;
weaken
$self
->{
' parent'
};
}
weaken
$self
->{
'Parent'
}
if
defined
$parent
;
return
$self
;
}
sub
_pdf {
my
(
$self
) =
@_
;
return
$self
->get_top()->{
' parent'
};
}
sub
find_page {
my
(
$self
,
$page_number
) =
@_
;
my
$top
=
$self
->get_top();
return
$top
->find_page_recursively(\
$page_number
);
}
sub
find_page_recursively {
my
(
$self
,
$page_number_ref
) =
@_
;
if
(
$self
->{
'Count'
}->realise()->val() <=
$$page_number_ref
) {
$$page_number_ref
-=
$self
->{
'Count'
}->val();
return
;
}
my
$result
;
foreach
my
$kid
(
$self
->{
'Kids'
}->realise()->elements()) {
if
(
$kid
->{
'Type'
}->realise()->val() eq
'Page'
) {
return
$kid
if
$$page_number_ref
== 0;
$$page_number_ref
--;
}
elsif
(
$result
=
$kid
->realise()->find_page_recursively(
$page_number_ref
)) {
return
$result
;
}
}
return
;
}
sub
add_page {
my
(
$self
,
$page
,
$page_number
) =
@_
;
my
$top
=
$self
->get_top();
$page_number
= -1
unless
defined
$page_number
and
$page_number
<=
$top
->{
'Count'
}->val();
my
$previous_page
;
if
(
$page_number
== -1) {
$previous_page
=
$top
->find_page(
$top
->{
'Count'
}->val() - 1);
}
else
{
$page_number
=
$top
->{
'Count'
}->val() +
$page_number
+ 1
if
$page_number
< 0;
$previous_page
=
$top
->find_page(
$page_number
);
}
my
$parent
;
if
(
defined
$previous_page
->{
'Parent'
}) {
$parent
=
$previous_page
->{
'Parent'
}->realise();
}
else
{
$parent
=
$self
;
}
my
$parent_kid_count
=
scalar
$parent
->{
'Kids'
}->realise()->elements();
my
$page_index
;
if
(
$page_number
== -1) {
$page_index
= -1;
}
else
{
for
(
$page_index
= 0;
$page_index
<
$parent_kid_count
;
$page_index
++) {
last
if
$parent
->{
'Kids'
}{
' val'
}[
$page_index
] eq
$previous_page
;
}
$page_index
= -1
if
$page_index
==
$parent_kid_count
;
}
$parent
->add_page_recursively(
$page
->realise(),
$page_index
);
for
(
$parent
=
$page
->{
'Parent'
};
defined
$parent
->{
'Parent'
};
$parent
=
$parent
->{
'Parent'
}->realise()) {
$parent
->set_modified();
$parent
->{
'Count'
}->realise()->{
'val'
}++;
}
$parent
->set_modified();
$parent
->{
'Count'
}->realise()->{
'val'
}++;
return
$page
;
}
sub
add_page_recursively {
my
(
$self
,
$page
,
$page_index
) =
@_
;
my
$parent
=
$self
;
my
$max_kids_per_parent
= 8;
if
(
scalar
$parent
->{
'Kids'
}->elements() >=
$max_kids_per_parent
and
$parent
->{
'Parent'
} and
$page_index
< 0) {
my
$grandparent
=
$parent
->{
'Parent'
}->realise();
$parent
=
$parent
->new(
$parent
->_pdf(),
$grandparent
);
my
$grandparent_kid_count
=
scalar
$grandparent
->{
'Kids'
}->realise()->elements();
my
$new_parent_index
;
for
(
$new_parent_index
= 0;
$new_parent_index
<
$grandparent_kid_count
;
$new_parent_index
++) {
last
if
$grandparent
->{
'Kids'
}{
' val'
}[
$new_parent_index
] eq
$self
;
}
$new_parent_index
++;
$new_parent_index
= -1
if
$new_parent_index
>
$grandparent_kid_count
;
$grandparent
->add_page_recursively(
$parent
,
$new_parent_index
);
}
else
{
$parent
->set_modified();
}
if
(
$page_index
< 0) {
push
@{
$parent
->{
'Kids'
}->realise()->{
' val'
}},
$page
;
}
else
{
splice
@{
$parent
->{
'Kids'
}{
' val'
}},
$page_index
, 0,
$page
;
}
$page
->{
'Parent'
} =
$parent
;
weaken
$page
->{
'Parent'
};
return
;
}
sub
set_modified {
my
(
$self
) =
@_
;
$self
->_pdf()->out_obj(
$self
);
return
;
}
sub
get_pages {
my
(
$self
) =
@_
;
return
$self
->get_top()->get_pages_recursively();
}
sub
get_kids {
return
get_pages_recursively(
@_
); }
sub
get_pages_recursively {
my
(
$self
) =
@_
;
my
@pages
;
foreach
my
$kid
(
$self
->{
'Kids'
}->elements()) {
$kid
->realise();
if
(
$kid
->{
'Type'
}->val() eq
'Pages'
) {
push
@pages
,
$kid
->get_pages_recursively();
}
else
{
push
@pages
,
$kid
;
}
}
return
@pages
;
}
sub
find_prop {
my
(
$self
,
$key
) =
@_
;
if
(
defined
$self
->{
$key
}) {
if
(
ref
(
$self
->{
$key
}) and
$self
->{
$key
}->isa(
'PDF::Builder::Basic::PDF::Objind'
)) {
return
$self
->{
$key
}->realise();
}
else
{
return
$self
->{
$key
};
}
}
elsif
(
defined
$self
->{
'Parent'
}) {
return
$self
->{
'Parent'
}->find_prop(
$key
);
}
return
;
}
sub
add_font {
my
(
$self
,
$pdf
,
$font
) =
@_
;
my
$name
=
$font
->{
'Name'
}->val();
my
$dict
=
$self
->find_prop(
'Resources'
);
return
$self
if
(
$dict
and
defined
$dict
->{
'Font'
} and
defined
$dict
->{
'Font'
}{
$name
});
unless
(
defined
$self
->{
'Resources'
}) {
$dict
=
$dict
?
$dict
->copy(
$pdf
) : PDFDict();
$self
->{
'Resources'
} =
$dict
;
}
else
{
$dict
=
$self
->{
'Resources'
};
}
$dict
->{
'Font'
} //= PDFDict();
my
$resource
=
$dict
->{
'Font'
}->val();
$resource
->{
$name
} //=
$font
;
if
(
ref
(
$dict
) ne
'HASH'
and
$dict
->is_obj(
$pdf
)) {
$pdf
->out_obj(
$dict
);
}
if
(
ref
(
$resource
) ne
'HASH'
and
$resource
->is_obj(
$pdf
)) {
$pdf
->out_obj(
$resource
);
}
return
$self
;
}
sub
bbox {
my
(
$self
,
@bbox
) =
@_
;
my
$key
=
$bbox
[4] ||
'MediaBox'
;
my
$inherited
=
$self
->find_prop(
$key
);
if
(
$inherited
) {
my
$is_changed
= 0;
my
$i
= 0;
foreach
my
$element
(
$inherited
->elements()) {
$is_changed
= 1
unless
$element
->val() ==
$bbox
[
$i
++];
}
return
$self
if
$i
== 4 and not
$is_changed
;
}
my
$array
= PDF::Builder::Basic::PDF::Array->new();
foreach
my
$element
(
@bbox
[0 .. 3]) {
$array
->add_elements(PDFNum(
$element
));
}
$self
->{
$key
} =
$array
;
return
$self
;
}
sub
proc_set {
my
(
$self
,
@entries
) =
@_
;
my
$dict
=
$self
->find_prop(
'Resources'
);
if
(
$dict
and
defined
$dict
->{
'ProcSet'
}) {
my
@missing
=
@entries
;
foreach
my
$element
(
$dict
->{
'ProcSet'
}->elements()) {
@missing
=
grep
{
$_
ne
$element
}
@missing
;
}
return
$self
if
scalar
@missing
== 0;
@entries
=
@missing
if
defined
$self
->{
'Resources'
};
}
unless
(
defined
$self
->{
'Resources'
}) {
$self
->{
'Resources'
} =
$dict
?
$dict
->copy(
$self
->_pdf()) : PDFDict();
}
$self
->{
'Resources'
}{
'ProcSet'
} = PDFArray()
unless
defined
$self
->{
'ProcSet'
};
foreach
my
$element
(
@entries
) {
$self
->{
'Resources'
}{
'ProcSet'
}->add_elements(PDFName(
$element
));
}
return
$self
;
}
sub
empty {
my
(
$self
) =
@_
;
my
$parent
=
$self
->{
'Parent'
};
$self
->SUPER::empty();
if
(
defined
$parent
) {
$self
->{
'Parent'
} =
$parent
;
weaken
$self
->{
'Parent'
};
}
return
$self
;
}
sub
get_top {
my
(
$self
) =
@_
;
my
$top
=
$self
;
$top
=
$top
->{
'Parent'
}
while
defined
$top
->{
'Parent'
};
return
$top
->realise();
}
1;