Skip to content
Snippets Groups Projects
Commit 3b30713b authored by Hartmut Henkel's avatar Hartmut Henkel
Browse files

Pages tree writing moved from luatex.web to utils.c, based on pdftex

1.50 page divert mechanism. Currently only the default diversion no. 0
is used, diversions are not yet user accessible.
parent a027fee4
No related branches found
No related tags found
No related merge requests found
......@@ -445,6 +445,9 @@
@define function getlly;
@define function geturx;
@define function getury;
@define function pdf_do_page_divert();
@define procedure pdf_do_page_undivert();
@define function output_pages_tree;
{functions from texpdf.c }
......
......@@ -15982,7 +15982,7 @@ end
@!fixed_pdf_draftmode: integer; {fixed \\pdfdraftmode}
@!epochseconds: integer;
@!microseconds: integer;
@!page_divert_val: integer;
 
@ @<Set init...@>=
pdf_gone := 0;
......@@ -15999,6 +15999,7 @@ pdf_seek_write_length := false;
zip_write_state := no_zip;
fixed_pdf_minor_version_set := false;
fixed_pdfoutput_set := false;
page_divert_val := 0;
 
@ @p
function fix_int(val, min, max: integer): integer;
......@@ -16847,7 +16848,7 @@ well.
@# {types of objects}
@d obj_type_others == 0 {objects which are not linked in any list}
@d obj_type_page == 1 {index of linked list of Page objects}
@d obj_type_pages == 2 {index of linked list of Pages objects}
@d obj_type_pages == 2 {obsolete: index of linked list of Pages objects}
@d obj_type_font == 3 {index of linked list of Fonts objects}
@d obj_type_outline == 4 {index of linked list of outline objects}
@d obj_type_dest == 5 {index of linked list of destination objects}
......@@ -18932,6 +18933,7 @@ pdf_print_ln(" ]")
 
@ @<Write out page object@>=
pdf_begin_dict(pdf_last_page, 1);
pdf_last_pages := pdf_do_page_divert(pdf_last_page, page_divert_val);
pdf_print_ln("/Type /Page");
pdf_indirect_ln("Contents", pdf_last_stream);
pdf_indirect_ln("Resources", pdf_last_resources);
......@@ -18941,17 +18943,10 @@ pdf_print_mag_bp(cur_page_height);
pdf_print_ln("]");
if pdf_page_attr <> null then
pdf_print_toks_ln(pdf_page_attr);
@<Generate parent pages object@>;
pdf_indirect_ln("Parent", pdf_last_pages);
@<Generate array of annotations or beads in page@>;
pdf_end_dict
 
@ @<Generate parent pages object@>=
if total_pages mod pages_tree_kids_max = 1 then begin
pdf_create_obj(obj_type_pages, pages_tree_kids_max);
pdf_last_pages := obj_ptr;
end;
pdf_indirect_ln("Parent", pdf_last_pages)
@ @<Generate array of annotations or beads in page@>=
if (pdf_annot_list <> null) or (pdf_link_list <> null) then begin
pdf_print("/Annots [ ");
......@@ -19431,10 +19426,9 @@ else begin
{last pages object may have less than |pages_tree_kids_max| children}
flush_jbig2_page0_objects; {flush page 0 objects from JBIG2 images, if any}
@<Check for non-existing pages@>;
@<Reverse the linked list of Page and Pages objects@>;
@<Check for non-existing destinations@>;
@<Output fonts definition@>;
@<Output pages tree@>;
pdf_last_pages := output_pages_tree;
@<Output outlines@>;
@<Output name tree@>;
@<Output article threads@>;
......@@ -19452,15 +19446,15 @@ else begin
end;
@<Output the trailer@>;
pdf_flush;
if callback_id=0 then begin
print_nl("Output written on "); print_file_name(0, output_file_name, 0);
@.Output written on x@>
print(" ("); print_int(total_pages); print(" page");
if total_pages<>1 then print_char("s");
print(", "); print_int(pdf_offset); print(" bytes).");
end
if callback_id=0 then begin
print_nl("Output written on "); print_file_name(0, output_file_name, 0);
@.Output written on x@>
print(" ("); print_int(total_pages); print(" page");
if total_pages<>1 then print_char("s");
print(", "); print_int(pdf_offset); print(" bytes).");
end
else
res:=run_callback(callback_id,'->');
res:=run_callback(callback_id,'->');
end;
libpdffinish;
if fixed_pdf_draftmode = 0 then b_close(pdf_file)
......@@ -19512,27 +19506,6 @@ while obj_aux(k) = 0 do begin
end;
head_tab[obj_type_page] := k
 
@ @<Reverse the linked list of Page and Pages objects@>=
k := head_tab[obj_type_page];
l := 0;
repeat
i := obj_link(k);
obj_link(k) := l;
l := k;
k := i;
until k = 0;
head_tab[obj_type_page] := l;
k := head_tab[obj_type_pages];
pages_tail := k;
l := 0;
repeat
i := obj_link(k);
obj_link(k) := l;
l := k;
k := i;
until k = 0;
head_tab[obj_type_pages] := l
@ @<Output fonts definition@>=
for k := 1 to max_font_id do
if font_used(k) and (pdf_font_num(k) < 0) then begin
......@@ -19564,77 +19537,12 @@ while k <> 0 do begin
end;
write_fontstuff
 
@ We will generate in each single step the parents of all Pages/Page objects in
the previous level. These new generated Pages object will create a new level of
Pages tree. We will repeat this until search only one Pages object. This one
will be the Root object.
@<Output pages tree@>=
a := sys_obj_ptr + 1; {all Pages objects whose children are not Page objects
should have index greater than |a|}
l := head_tab[obj_type_pages]; {|l| is the index of current Pages object
which is being output}
k := head_tab[obj_type_page]; {|k| is the index of current child of |l|}
b := 0;
repeat
i := 0; {counter of Pages object in current level}
c := 0; {first Pages object in previous level}
if obj_link(l) = 0 then
is_root := true {only Pages object; total pages is
not greater than |pages_tree_kids_max|}
else
is_root := false;
repeat
if not is_root then begin
if i mod pages_tree_kids_max = 0 then begin {create a new Pages object
for next level}
pdf_last_pages := pdf_new_objnum;
if c = 0 then
c := pdf_last_pages;
obj_link(pages_tail) := pdf_last_pages;
pages_tail := pdf_last_pages;
obj_link(pdf_last_pages) := 0;
obj_info(pdf_last_pages) := obj_info(l);
end
else
obj_info(pdf_last_pages) := obj_info(pdf_last_pages) +
obj_info(l);
end;
@<Output the current Pages object in this level@>;
incr(i);
l := obj_link(l);
until (l = c);
b := c;
if l = 0 then
goto done;
until false;
done:
@ @<Output the current Pages object in this level@>=
pdf_begin_dict(l, 1);
pdf_print_ln("/Type /Pages");
pdf_int_entry_ln("Count", obj_info(l));
if not is_root then
pdf_indirect_ln("Parent", pdf_last_pages);
pdf_print("/Kids [");
j := 0;
repeat
pdf_print_int(k);
pdf_print(" 0 R ");
k := obj_link(k);
incr(j);
until ((l < a) and (j = obj_info(l))) or
(k = 0) or ((k = b) and (b <> 0)) or
(j = pages_tree_kids_max);
remove_last_space;
pdf_print_ln("]");
if k = 0 then begin
k := head_tab[obj_type_pages];
head_tab[obj_type_pages] := 0;
@ @p
procedure print_pdf_pages_attr;
begin
if pdf_pages_attr <> null then
pdf_print_toks_ln(pdf_pages_attr);
end;
if is_root and (pdf_pages_attr <> null) then
pdf_print_toks_ln(pdf_pages_attr);
pdf_end_dict;
 
@ The name tree is very similiar to Pages tree so its construction should be
certain from Pages tree construction. For intermediate node |obj_info| will be
......@@ -274,6 +274,9 @@ extern scaled getllx();
extern scaled getlly();
extern scaled geturx();
extern scaled getury();
extern integer pdf_do_page_divert(integer, integer);
extern void pdf_do_page_undivert(integer, integer);
extern integer output_pages_tree();
/* writeenc.c */
extern fe_entry *get_fe_entry(char *);
......
......@@ -1817,3 +1817,235 @@ void tconfusion(char *s)
{
confusion(maketexstring(s));
}
/**********************************************************************/
/* Page diversions */
#ifdef DEBUG
# define PAGES_TREE_KIDSMAX 3
#else
# define PAGES_TREE_KIDSMAX 6
#endif
static struct avl_table *divert_list_tree = NULL;
typedef struct pages_entry_ {
integer objnum; /* object number of this /Pages object */
integer number_of_pages; /* total number of all pages below */
integer number_of_kids; /* number of direct kid objects */
integer kids[PAGES_TREE_KIDSMAX]; /* array of kid object numbers */
struct pages_entry_ *next;
} pages_entry;
typedef struct divert_list_entry_ {
integer divnum;
pages_entry *first;
pages_entry *last;
} divert_list_entry;
static int comp_divert_list_entry(const void *pa, const void *pb, void *p)
{
if (((const divert_list_entry *) pa)->divnum >
((const divert_list_entry *) pb)->divnum)
return 1;
if (((const divert_list_entry *) pa)->divnum <
((const divert_list_entry *) pb)->divnum)
return -1;
return 0;
}
static pages_entry *new_pages_entry()
{
pages_entry *p;
int i;
p = xtalloc(1, pages_entry);
p->number_of_pages = p->number_of_kids = 0;
for (i = 0; i < PAGES_TREE_KIDSMAX; i++)
p->kids[i] = 0;
p->next = NULL;
pdf_create_obj(0, 0);
p->objnum = obj_ptr;
return p;
}
static divert_list_entry *new_divert_list_entry()
{
divert_list_entry *d;
d = xtalloc(1, divert_list_entry);
d->first = d->last = NULL;
return d;
}
static void ensure_list_tree()
{
if (divert_list_tree == NULL) {
divert_list_tree =
avl_create(comp_divert_list_entry, NULL, &avl_xallocator);
assert(divert_list_tree != NULL);
}
}
static divert_list_entry *get_divert_list(integer divnum)
{
divert_list_entry *d, tmp;
void **aa;
tmp.divnum = divnum;
d = (divert_list_entry *) avl_find(divert_list_tree, &tmp);
if (d == NULL) {
d = new_divert_list_entry();
d->divnum = divnum;
aa = avl_probe(divert_list_tree, d);
assert(aa != NULL);
}
return d;
}
/* pdf_do_page_divert() returns the current /Parent object number */
integer pdf_do_page_divert(integer objnum, integer divnum)
{
divert_list_entry *d;
pages_entry *p;
#ifdef DEBUG
pages_entry *q;
struct avl_traverser t;
int i;
#endif
// initialize the tree
ensure_list_tree();
// make sure we have a list for this diversion
d = get_divert_list(divnum);
if (d->first == NULL || d->last->number_of_kids == PAGES_TREE_KIDSMAX) {
// append a new pages_entry
p = new_pages_entry();
if (d->first == NULL)
d->first = p;
else
d->last->next = p;
d->last = p;
}
p = d->last;
p->kids[p->number_of_kids++] = objnum;
p->number_of_pages++;
#ifdef DEBUG
printf("\n");
avl_t_init(&t, divert_list_tree);
for (d = avl_t_first(&t, divert_list_tree); d != NULL; d = avl_t_next(&t)) {
printf("===== D-LIST %d: ", d->divnum);
for (q = d->first; q != NULL; q = q->next) {
printf("P=%d NK=%d (", q->objnum, q->number_of_kids);
for (i = 0; i < q->number_of_kids; i++)
printf("%d ", q->kids[i]);
printf(") ");
}
printf("\n");
}
printf("\n");
#endif
return p->objnum;
}
static void movelist(divert_list_entry * d, divert_list_entry * dto)
{
if (d != NULL && d->first != NULL && d->divnum != dto->divnum) { /* no undivert of empty list or into self */
if (dto->first == NULL)
dto->first = d->first;
else
dto->last->next = d->first;
dto->last = d->last;
d->first = d->last = NULL; /* one could as well remove this divert_list_entry */
}
}
/* undivert from diversion <divnum> into diversion <curdivnum> */
void pdf_do_page_undivert(integer divnum, integer curdivnum)
{
divert_list_entry *d, *dto, tmp;
struct avl_traverser t;
#ifdef DEBUG
pages_entry *p;
int i;
#endif
// initialize the tree
ensure_list_tree();
// find the diversion <curdivnum> list where diversion <divnum> should go
dto = get_divert_list(curdivnum);
if (divnum == 0) { /* 0 = special case: undivert _all_ lists */
avl_t_init(&t, divert_list_tree);
for (d = avl_t_first(&t, divert_list_tree); d != NULL;
d = avl_t_next(&t))
movelist(d, dto);
} else {
tmp.divnum = divnum;
d = (divert_list_entry *) avl_find(divert_list_tree, &tmp);
movelist(d, dto);
}
#ifdef DEBUG
printf("\n");
avl_t_init(&t, divert_list_tree);
for (d = avl_t_first(&t, divert_list_tree); d != NULL; d = avl_t_next(&t)) {
printf("===== U-LIST %d: ", d->divnum);
for (p = d->first; p != NULL; p = p->next) {
printf("P=%d NK=%d (", p->objnum, p->number_of_kids);
for (i = 0; i < p->number_of_kids; i++)
printf("%d ", p->kids[i]);
printf(") ");
}
printf("\n");
}
printf("\n");
#endif
}
/* write a /Pages object */
static void write_pages(pages_entry * p, int parent)
{
int i;
assert(p != NULL);
pdf_begin_dict(p->objnum, 1);
pdf_printf("/Type /Pages\n");
if (parent == 0) /* it's root */
print_pdf_pages_attr();
else
pdf_printf("/Parent %d 0 R\n", parent);
pdf_printf("/Count %d\n/Kids [", p->number_of_pages);
for (i = 0; i < p->number_of_kids; i++)
pdf_printf("%d 0 R ", p->kids[i]);
remove_last_space();
pdf_printf("]\n");
pdf_end_dict();
}
/* loop over all /Pages objects, output them, create their parents,
* recursing bottom up, return the /Pages root object number */
static integer output_pages_list(pages_entry * pe)
{
pages_entry *p, *q, *r;
assert(pe != NULL);
if (pe->next == NULL) { /* everything fits into one pages_entry */
write_pages(pe, 0); /* --> /Pages root found */
return pe->objnum;
}
q = r = new_pages_entry(); /* one level higher needed */
for (p = pe; p != NULL; p = p->next) {
if (q->number_of_kids == PAGES_TREE_KIDSMAX) {
q->next = new_pages_entry();
q = q->next;
}
q->kids[q->number_of_kids++] = p->objnum;
q->number_of_pages += p->number_of_pages;
write_pages(p, q->objnum);
}
return output_pages_list(r); /* recurse through next higher level */
}
integer output_pages_tree()
{
divert_list_entry *d;
pdf_do_page_undivert(0, 0); /* concatenate all diversions into diversion 0 */
d = get_divert_list(0); /* get diversion 0 */
return output_pages_list(d->first);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment