diff options
author | Luigi Scarso <luigi.scarso@gmail.com> | 2018-09-05 21:57:30 +0000 |
---|---|---|
committer | Luigi Scarso <luigi.scarso@gmail.com> | 2018-09-05 21:57:30 +0000 |
commit | ecd1605a23ef54d2a4a69e1a361172d350e03b3b (patch) | |
tree | 8ea1d9745c24dbc5e755f13d801fa01e88944650 /Build/source/texk/web2c/luatexdir/pdf/pdfdest.c | |
parent | 04563248956e7059aad4fc4f6bf7da18562f7b8c (diff) |
luatex: correct automake file for pplib; replaced cweb files with c files.
git-svn-id: svn://tug.org/texlive/trunk@48594 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/pdf/pdfdest.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/pdf/pdfdest.c | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/pdf/pdfdest.c b/Build/source/texk/web2c/luatexdir/pdf/pdfdest.c new file mode 100644 index 00000000000..346cd26e031 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/pdf/pdfdest.c @@ -0,0 +1,401 @@ +/* + +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 + + Here we implement subroutines for work with objects and related things. Some + of them are used in former parts too, so we need to declare them forward. + Memory will grow dynamically. + +*/ + +void init_dest_names(PDF pdf) +{ + pdf->dest_names_size = inf_dest_names_size; + pdf->dest_names = xmallocarray(dest_name_entry, inf_dest_names_size); +} + +void append_dest_name(PDF pdf, char *s, int n) +{ + int a; + if (pdf->dest_names_ptr == sup_dest_names_size) + overflow("number of destination names (dest_names_size)",(unsigned) pdf->dest_names_size); + if (pdf->dest_names_ptr == pdf->dest_names_size) { + a = pdf->dest_names_size / 5; + if (pdf->dest_names_size < sup_dest_names_size - a) + pdf->dest_names_size = pdf->dest_names_size + a; + else + pdf->dest_names_size = sup_dest_names_size; + pdf->dest_names = xreallocarray(pdf->dest_names, dest_name_entry, (unsigned) pdf->dest_names_size); + } + pdf->dest_names[pdf->dest_names_ptr].objname = xstrdup(s); + pdf->dest_names[pdf->dest_names_ptr].objnum = n; + pdf->dest_names_ptr++; +} + +/*tex + + When a destination is created we need to check whether another destination + with the same identifier already exists and give a warning if needed. + +*/ + +static void warn_dest_dup(int id, small_number byname) +{ + if (byname > 0) { + char *ss = tokenlist_to_cstring(id, true, NULL); + formatted_warning("pdf backend", "ignoring duplicate destination with the name '%s'",ss); + } else { + formatted_warning("pdf backend", "ignoring duplicate destination with the num '%d'",id); + } +} + +void do_dest(PDF pdf, halfword p, halfword parent_box, scaledpos cur) +{ + scaledpos pos = pdf->posstruct->pos; + scaled_whd alt_rule; + int k; + if (global_shipping_mode == SHIPPING_FORM) + normal_error("pdf backend", "destinations cannot be inside an xform"); + if (doing_leaders) + return; + k = pdf_get_obj(pdf, obj_type_dest, pdf_dest_id(p), pdf_dest_named_id(p)); + if (obj_dest_ptr(pdf, k) != null) { + warn_dest_dup(pdf_dest_id(p), (small_number) pdf_dest_named_id(p)); + return; + } + obj_dest_ptr(pdf, k) = p; + addto_page_resources(pdf, obj_type_dest, k); + alt_rule.wd = width(p); + alt_rule.ht = height(p); + alt_rule.dp = depth(p); + /*tex + The different branches for matrixused is somewhat strange and should + always be used + */ + switch (pdf_dest_type(p)) { + case pdf_dest_xyz: + if (matrixused()) + set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_dest_margin); + else { + pdf_ann_left(p) = pos.h; + pdf_ann_top(p) = pos.v; + } + break; + case pdf_dest_fith: + case pdf_dest_fitbh: + if (matrixused()) + set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_dest_margin); + else + pdf_ann_top(p) = pos.v; + break; + case pdf_dest_fitv: + case pdf_dest_fitbv: + if (matrixused()) + set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_dest_margin); + else + pdf_ann_left(p) = pos.h; + break; + case pdf_dest_fit: + case pdf_dest_fitb: + break; + case pdf_dest_fitr: + set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_dest_margin); + } +} + +void write_out_pdf_mark_destinations(PDF pdf) +{ + pdf_object_list *k; + if ((k = get_page_resources_list(pdf, obj_type_dest)) != NULL) { + while (k != NULL) { + if (is_obj_written(pdf, k->info)) { + normal_error("pdf backend","destination has been already written (this shouldn't happen)"); + } else { + int i; + i = obj_dest_ptr(pdf, k->info); + pdf_begin_obj(pdf, k->info, OBJSTM_ALWAYS); + if (pdf_dest_named_id(i) > 0) { + pdf_begin_dict(pdf); + pdf_add_name(pdf, "D"); + } + pdf_begin_array(pdf); + pdf_add_ref(pdf, pdf->last_page); + switch (pdf_dest_type(i)) { + case pdf_dest_xyz: + pdf_add_name(pdf, "XYZ"); + pdf_add_bp(pdf, pdf_ann_left(i)); + pdf_add_bp(pdf, pdf_ann_top(i)); + if (pdf_dest_xyz_zoom(i) == null) { + pdf_add_null(pdf); + } else { + pdf_check_space(pdf); + pdf_print_int(pdf, pdf_dest_xyz_zoom(i) / 1000); + pdf_out(pdf, '.'); + pdf_print_int(pdf, (pdf_dest_xyz_zoom(i) % 1000)); + pdf_set_space(pdf); + } + break; + case pdf_dest_fit: + pdf_add_name(pdf, "Fit"); + break; + case pdf_dest_fith: + pdf_add_name(pdf, "FitH"); + pdf_add_bp(pdf, pdf_ann_top(i)); + break; + case pdf_dest_fitv: + pdf_add_name(pdf, "FitV"); + pdf_add_bp(pdf, pdf_ann_left(i)); + break; + case pdf_dest_fitb: + pdf_add_name(pdf, "FitB"); + break; + case pdf_dest_fitbh: + pdf_add_name(pdf, "FitBH"); + pdf_add_bp(pdf, pdf_ann_top(i)); + break; + case pdf_dest_fitbv: + pdf_add_name(pdf, "FitBV"); + pdf_add_bp(pdf, pdf_ann_left(i)); + break; + case pdf_dest_fitr: + pdf_add_name(pdf, "FitR"); + pdf_add_rect_spec(pdf, i); + break; + default: + normal_error("pdf backend", "unknown dest type"); + break; + } + pdf_end_array(pdf); + if (pdf_dest_named_id(i) > 0) + pdf_end_dict(pdf); + pdf_end_obj(pdf); + } + k = k->link; + } + } +} + +void scan_pdfdest(PDF pdf) +{ + halfword q; + int k; + str_number i; + scaled_whd alt_rule; + q = cur_list.tail_field; + new_whatsit(pdf_dest_node); + if (scan_keyword("num")) { + scan_int(); + if (cur_val <= 0) + normal_error("pdf backend", "num identifier must be positive"); + if (cur_val > max_halfword) + normal_error("pdf backend", "number too big"); + set_pdf_dest_id(cur_list.tail_field, cur_val); + set_pdf_dest_named_id(cur_list.tail_field, 0); + } else if (scan_keyword("name")) { + scan_toks(false, true); + set_pdf_dest_id(cur_list.tail_field, def_ref); + set_pdf_dest_named_id(cur_list.tail_field, 1); + } else { + normal_error("pdf backend", "identifier type missing"); + } + if (scan_keyword("xyz")) { + set_pdf_dest_type(cur_list.tail_field, pdf_dest_xyz); + if (scan_keyword("zoom")) { + scan_int(); + if (cur_val > max_halfword) + normal_error("pdf backend", "number too big"); + set_pdf_dest_xyz_zoom(cur_list.tail_field, cur_val); + } else { + set_pdf_dest_xyz_zoom(cur_list.tail_field, null); + } + } else if (scan_keyword("fitbh")) { + set_pdf_dest_type(cur_list.tail_field, pdf_dest_fitbh); + } else if (scan_keyword("fitbv")) { + set_pdf_dest_type(cur_list.tail_field, pdf_dest_fitbv); + } else if (scan_keyword("fitb")) { + set_pdf_dest_type(cur_list.tail_field, pdf_dest_fitb); + } else if (scan_keyword("fith")) { + set_pdf_dest_type(cur_list.tail_field, pdf_dest_fith); + } else if (scan_keyword("fitv")) { + set_pdf_dest_type(cur_list.tail_field, pdf_dest_fitv); + } else if (scan_keyword("fitr")) { + set_pdf_dest_type(cur_list.tail_field, pdf_dest_fitr); + } else if (scan_keyword("fit")) { + set_pdf_dest_type(cur_list.tail_field, pdf_dest_fit); + } else { + normal_error("pdf backend", "destination type missing"); + } + /*tex Scan an optional space. */ + get_x_token(); + if (cur_cmd != spacer_cmd) + back_input(); + if (pdf_dest_type(cur_list.tail_field) == pdf_dest_fitr) { + alt_rule = scan_alt_rule(); + set_width(cur_list.tail_field, alt_rule.wd); + set_height(cur_list.tail_field, alt_rule.ht); + set_depth(cur_list.tail_field, alt_rule.dp); + } + if (pdf_dest_named_id(cur_list.tail_field) != 0) { + i = tokens_to_string(pdf_dest_id(cur_list.tail_field)); + k = find_obj(pdf, obj_type_dest, i, true); + flush_str(i); + } else { + k = find_obj(pdf, obj_type_dest, pdf_dest_id(cur_list.tail_field), false); + } + if ((k != 0) && (obj_dest_ptr(pdf, k) != null)) { + warn_dest_dup(pdf_dest_id(cur_list.tail_field),(small_number) pdf_dest_named_id(cur_list.tail_field)); + flush_node_list(cur_list.tail_field); + cur_list.tail_field = q; + vlink(q) = null; + } +} + +/*tex Sort |dest_names| by names: */ + +static int dest_cmp(const void *a, const void *b) +{ + dest_name_entry aa = *(const dest_name_entry *) a; + dest_name_entry bb = *(const dest_name_entry *) b; + return strcmp(aa.objname, bb.objname); +} + +void sort_dest_names(PDF pdf) +{ + qsort(pdf->dest_names, (size_t) pdf->dest_names_ptr, sizeof(dest_name_entry), dest_cmp); +} + +/*tex + + Output the name tree. The tree nature of the destination list forces the + storing of intermediate data in |obj_info| and |obj_aux| fields, which is + further uglified by the fact that |obj_tab| entries do not accept char + pointers. + +*/ + +int output_name_tree(PDF pdf) +{ + /*tex A flag for name tree output: is it |/Names| or |/Kids|: */ + boolean is_names = true; + /*tex + The index of current child of |l|; if |k < pdf_dest_names_ptr| then this + is pointer to |dest_names| array; otherwise it is the pointer to + |obj_tab| (object number). + */ + int k = 0; + int b = 0; + int m, j, l; + int dests = 0; + int names_head = 0; + int names_tail = 0; + if (pdf->dest_names_ptr == 0) { + goto DONE; + } + sort_dest_names(pdf); + while (true) { + do { + /*tex Create a new node: */ + l = pdf_create_obj(pdf, obj_type_others, 0); + if (b == 0) { + /*tex First in this level: */ + b = l; + } + if (names_head == 0) { + names_head = l; + names_tail = l; + } else { + set_obj_link(pdf, names_tail, l); + names_tail = l; + } + set_obj_link(pdf, names_tail, 0); + /*tex Output the current node in this level. */ + pdf_begin_obj(pdf, l, OBJSTM_ALWAYS); + pdf_begin_dict(pdf); + j = 0; + if (is_names) { + set_obj_start(pdf, l, pdf->dest_names[k].objname); + pdf_add_name(pdf, "Names"); + pdf_begin_array(pdf); + do { + pdf_add_string(pdf, pdf->dest_names[k].objname); + pdf_add_ref(pdf, pdf->dest_names[k].objnum); + j++; + k++; + } while (j != name_tree_kids_max && k != pdf->dest_names_ptr); + pdf_end_array(pdf); + /*tex For later use: */ + set_obj_stop(pdf, l, pdf->dest_names[k - 1].objname); + if (k == pdf->dest_names_ptr) { + is_names = false; + k = names_head; + b = 0; + } + } else { + set_obj_start(pdf, l, obj_start(pdf, k)); + pdf_add_name(pdf, "Kids"); + pdf_begin_array(pdf); + do { + pdf_add_ref(pdf, k); + set_obj_stop(pdf, l, obj_stop(pdf, k)); + k = obj_link(pdf, k); + j++; + } while (j != name_tree_kids_max && k != b + && obj_link(pdf, k) != 0); + pdf_end_array(pdf); + if (k == b) + b = 0; + } + pdf_add_name(pdf, "Limits"); + pdf_begin_array(pdf); + pdf_add_string(pdf, obj_start(pdf, l)); + pdf_add_string(pdf, obj_stop(pdf, l)); + pdf_end_array(pdf); + pdf_end_dict(pdf); + pdf_end_obj(pdf); + } while (b != 0); + if (k == l) { + dests = l; + goto DONE; + } + } + DONE: + if ((dests != 0) || (pdf_names_toks != null)) { + m = pdf_create_obj(pdf, obj_type_others, 0); + pdf_begin_obj(pdf, m, OBJSTM_ALWAYS); + pdf_begin_dict(pdf); + if (dests != 0) + pdf_dict_add_ref(pdf, "Dests", dests); + if (pdf_names_toks != null) { + pdf_print_toks(pdf, pdf_names_toks); + delete_token_ref(pdf_names_toks); + pdf_names_toks = null; + } + print_pdf_table_string(pdf, "names"); + pdf_end_dict(pdf); + pdf_end_obj(pdf); + return m; + } else { + return 0; + } +} |