summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/pdf/pdfoutline.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/pdf/pdfoutline.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/pdf/pdfoutline.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/pdf/pdfoutline.c b/Build/source/texk/web2c/luatexdir/pdf/pdfoutline.c
new file mode 100644
index 00000000000..ae17e29dac3
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/pdf/pdfoutline.c
@@ -0,0 +1,259 @@
+/*
+
+Copyright 2009-2011 Taco Hoekwater <taco@@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License along
+with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "ptexlib.h"
+
+/*tex
+
+ Data structure of outlines; it's not able to write out outline entries before
+ all outline entries are defined, so memory allocated for outline entries
+ can't not be deallocated and will stay in memory. For this reason we will
+ store data of outline entries in |pdf->mem| instead of |mem|.
+
+*/
+
+/*tex The size of memory in |pdf->mem| which |obj_outline_ptr| points to: */
+
+#define pdfmem_outline_size 8
+
+/*tex The count of all opened children: */
+
+#define obj_outline_count obj_info
+
+/*tex The pointer to |pdf->mem|: */
+
+#define obj_outline_ptr obj_aux
+
+#define obj_outline_title(pdf,A) pdf->mem[obj_outline_ptr(pdf,A)]
+#define obj_outline_parent(pdf,A) pdf->mem[obj_outline_ptr(pdf,A) + 1]
+#define obj_outline_prev(pdf,A) pdf->mem[obj_outline_ptr(pdf,A) + 2]
+#define obj_outline_next(pdf,A) pdf->mem[obj_outline_ptr(pdf,A) + 3]
+#define obj_outline_first(pdf,A) pdf->mem[obj_outline_ptr(pdf,A) + 4]
+#define obj_outline_last(pdf,A) pdf->mem[obj_outline_ptr(pdf,A) + 5]
+#define obj_outline_action_objnum(pdf,A) pdf->mem[obj_outline_ptr(pdf,A) + 6]
+#define obj_outline_attr(pdf,A) pdf->mem[obj_outline_ptr(pdf,A) + 7]
+
+#define set_obj_outline_count(pdf,A,B) obj_outline_count(pdf,A)=B
+#define set_obj_outline_ptr(pdf,A,B) obj_outline_ptr(pdf,A)=B
+#define set_obj_outline_action_objnum(pdf,A,B) obj_outline_action_objnum(pdf,A)=B
+#define set_obj_outline_title(pdf,A,B) obj_outline_title(pdf,A)=B
+#define set_obj_outline_prev(pdf,A,B) obj_outline_prev(pdf,A)=B
+#define set_obj_outline_next(pdf,A,B) obj_outline_next(pdf,A)=B
+#define set_obj_outline_first(pdf,A,B) obj_outline_first(pdf,A)=B
+#define set_obj_outline_last(pdf,A,B) obj_outline_last(pdf,A)=B
+#define set_obj_outline_parent(pdf,A,B) obj_outline_parent(pdf,A)=B
+#define set_obj_outline_attr(pdf,A,B) obj_outline_attr(pdf,A)=B
+
+static int open_subentries(PDF pdf, halfword p)
+{
+ int c, l, r;
+ int k = 0;
+ if (obj_outline_first(pdf, p) != 0) {
+ l = obj_outline_first(pdf, p);
+ do {
+ k++;
+ c = open_subentries(pdf, l);
+ if (obj_outline_count(pdf, l) > 0)
+ k = k + c;
+ obj_outline_parent(pdf, l) = p;
+ r = obj_outline_next(pdf, l);
+ if (r == 0)
+ obj_outline_last(pdf, p) = l;
+ l = r;
+ } while (l != 0);
+ }
+ if (obj_outline_count(pdf, p) > 0)
+ obj_outline_count(pdf, p) = k;
+ else
+ obj_outline_count(pdf, p) = -k;
+ return k;
+}
+
+/*tex Return the number of outline entries in the same level with |p|: */
+
+static int outline_list_count(PDF pdf, pointer p)
+{
+ int k = 1;
+ while (obj_outline_prev(pdf, p) != 0) {
+ k++;
+ p = obj_outline_prev(pdf, p);
+ }
+ return k;
+}
+
+void scan_pdfoutline(PDF pdf)
+{
+ halfword q, r;
+ int i, k, l;
+ int j = 0;
+ halfword p = null;
+ if (scan_keyword("attr")) {
+ scan_toks(false, true);
+ r = def_ref;
+ } else {
+ r = 0;
+ }
+ if (scan_keyword("useobjnum")) {
+ scan_int();
+ j = cur_val;
+ } else {
+ p = scan_action(pdf);
+ }
+ if (scan_keyword("count")) {
+ scan_int();
+ i = cur_val;
+ } else {
+ i = 0;
+ }
+ scan_toks(false, true);
+ q = def_ref;
+ if (j == 0) {
+ j = pdf_create_obj(pdf, obj_type_others, 0);
+ pdf_begin_obj(pdf, j, OBJSTM_ALWAYS);
+ write_action(pdf, p);
+ pdf_end_obj(pdf);
+ delete_action_ref(p);
+ }
+ k = pdf_create_obj(pdf, obj_type_outline, 0);
+ set_obj_outline_ptr(pdf, k, pdf_get_mem(pdf, pdfmem_outline_size));
+ set_obj_outline_action_objnum(pdf, k, j);
+ set_obj_outline_count(pdf, k, i);
+ l = pdf_create_obj(pdf, obj_type_others, 0);
+ pdf_begin_obj(pdf, l, OBJSTM_ALWAYS);
+ {
+ char *s = tokenlist_to_cstring(q, true, NULL);
+ pdf_print_str_ln(pdf, s);
+ xfree(s);
+ }
+ delete_token_ref(q);
+ pdf_end_obj(pdf);
+ set_obj_outline_title(pdf, k, l);
+ set_obj_outline_prev(pdf, k, 0);
+ set_obj_outline_next(pdf, k, 0);
+ set_obj_outline_first(pdf, k, 0);
+ set_obj_outline_last(pdf, k, 0);
+ set_obj_outline_parent(pdf, k, pdf->parent_outline);
+ set_obj_outline_attr(pdf, k, r);
+ if (pdf->first_outline == 0)
+ pdf->first_outline = k;
+ if (pdf->last_outline == 0) {
+ if (pdf->parent_outline != 0)
+ set_obj_outline_first(pdf, pdf->parent_outline, k);
+ } else {
+ set_obj_outline_next(pdf, pdf->last_outline, k);
+ set_obj_outline_prev(pdf, k, pdf->last_outline);
+ }
+ pdf->last_outline = k;
+ if (obj_outline_count(pdf, k) != 0) {
+ pdf->parent_outline = k;
+ pdf->last_outline = 0;
+ } else if ((pdf->parent_outline != 0) &&
+ (outline_list_count(pdf, k) ==
+ abs(obj_outline_count(pdf, pdf->parent_outline)))) {
+ j = pdf->last_outline;
+ do {
+ set_obj_outline_last(pdf, pdf->parent_outline, j);
+ j = pdf->parent_outline;
+ pdf->parent_outline = obj_outline_parent(pdf, pdf->parent_outline);
+ } while (!((pdf->parent_outline == 0) ||
+ (outline_list_count(pdf, j) <
+ abs(obj_outline_count(pdf, pdf->parent_outline)))));
+ if (pdf->parent_outline == 0)
+ pdf->last_outline = pdf->first_outline;
+ else
+ pdf->last_outline = obj_outline_first(pdf, pdf->parent_outline);
+ while (obj_outline_next(pdf, pdf->last_outline) != 0)
+ pdf->last_outline = obj_outline_next(pdf, pdf->last_outline);
+ }
+}
+
+/*tex
+
+ In the end we must flush \PDF\F objects that cannot be written out
+ immediately after shipping out pages.
+
+*/
+
+int print_outlines(PDF pdf)
+{
+ int k, l, a;
+ int outlines;
+ if (pdf->first_outline != 0) {
+ outlines = pdf_create_obj(pdf, obj_type_others, 0);
+ l = pdf->first_outline;
+ k = 0;
+ do {
+ k++;
+ a = open_subentries(pdf, l);
+ if (obj_outline_count(pdf, l) > 0)
+ k = k + a;
+ set_obj_outline_parent(pdf, l, pdf->obj_ptr);
+ l = obj_outline_next(pdf, l);
+ } while (l != 0);
+ pdf_begin_obj(pdf, outlines, OBJSTM_ALWAYS);
+ pdf_begin_dict(pdf);
+ pdf_dict_add_name(pdf, "Type", "Outlines");
+ pdf_dict_add_ref(pdf, "First", pdf->first_outline);
+ pdf_dict_add_ref(pdf, "Last", pdf->last_outline);
+ pdf_dict_add_int(pdf, "Count", k);
+ pdf_end_dict(pdf);
+ pdf_end_obj(pdf);
+ /*tex Output \PDF\ outline entries. */
+ k = pdf->head_tab[obj_type_outline];
+ while (k != 0) {
+ if (obj_outline_parent(pdf, k) == pdf->parent_outline) {
+ if (obj_outline_prev(pdf, k) == 0)
+ pdf->first_outline = k;
+ if (obj_outline_next(pdf, k) == 0)
+ pdf->last_outline = k;
+ }
+ pdf_begin_obj(pdf, k, OBJSTM_ALWAYS);
+ pdf_begin_dict(pdf);
+ pdf_dict_add_ref(pdf, "Title", obj_outline_title(pdf, k));
+ pdf_dict_add_ref(pdf, "A", obj_outline_action_objnum(pdf, k));
+ if (obj_outline_parent(pdf, k) != 0)
+ pdf_dict_add_ref(pdf, "Parent", obj_outline_parent(pdf, k));
+ if (obj_outline_prev(pdf, k) != 0)
+ pdf_dict_add_ref(pdf, "Prev", obj_outline_prev(pdf, k));
+ if (obj_outline_next(pdf, k) != 0)
+ pdf_dict_add_ref(pdf, "Next", obj_outline_next(pdf, k));
+ if (obj_outline_first(pdf, k) != 0)
+ pdf_dict_add_ref(pdf, "First", obj_outline_first(pdf, k));
+ if (obj_outline_last(pdf, k) != 0)
+ pdf_dict_add_ref(pdf, "Last", obj_outline_last(pdf, k));
+ if (obj_outline_count(pdf, k) != 0)
+ pdf_dict_add_int(pdf, "Count", obj_outline_count(pdf, k));
+ if (obj_outline_attr(pdf, k) != 0) {
+ pdf_out(pdf, '\n');
+ pdf_print_toks(pdf, obj_outline_attr(pdf, k));
+ pdf_out(pdf, '\n');
+ delete_token_ref(obj_outline_attr(pdf, k));
+ set_obj_outline_attr(pdf, k, null);
+ }
+ pdf_end_dict(pdf);
+ pdf_end_obj(pdf);
+ k = obj_link(pdf, k);
+ }
+ } else {
+ outlines = 0;
+ }
+ return outlines;
+}