diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/pdf/pdflink.w')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/pdf/pdflink.w | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/pdf/pdflink.w b/Build/source/texk/web2c/luatexdir/pdf/pdflink.w new file mode 100644 index 00000000000..66b369d12bd --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/pdf/pdflink.w @@ -0,0 +1,166 @@ +% pdflink.w + +% Copyright 2009-2010 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/>. + +@ @c +static const char _svn_version[] = + "$Id: pdflink.w 3571 2010-04-02 13:50:45Z taco $" + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/pdf/pdflink.w $"; + +#include "ptexlib.h" + +@ @c +#define pdf_link_margin dimen_par(pdf_link_margin_code) + +@ To implement nested link annotations, we need a stack to hold copy of +|pdf_start_link_node|'s that are being written out, together with their box +nesting level. + +@c +void push_link_level(PDF pdf, halfword p) +{ + if (pdf->link_stack_ptr >= pdf_max_link_level) + overflow("pdf link stack size", pdf_max_link_level); + assert(((type(p) == whatsit_node) && (subtype(p) == pdf_start_link_node))); + incr(pdf->link_stack_ptr); + pdf->link_stack[pdf->link_stack_ptr].nesting_level = cur_s; + pdf->link_stack[pdf->link_stack_ptr].link_node = copy_node_list(p); + pdf->link_stack[pdf->link_stack_ptr].ref_link_node = p; +} + +@ @c +void pop_link_level(PDF pdf) +{ + assert(pdf->link_stack_ptr > 0); + flush_node_list(pdf->link_stack[pdf->link_stack_ptr].link_node); + decr(pdf->link_stack_ptr); +} + +@ @c +void do_link(PDF pdf, halfword p, halfword parent_box, scaledpos cur) +{ + scaled_whd alt_rule; + if (type(p) == vlist_node) + pdf_error("ext4", "\\pdfstartlink ended up in vlist"); + if (!is_shipping_page) + pdf_error("ext4", "link annotations cannot be inside an XForm"); + assert(type(parent_box) == hlist_node); + if (is_obj_scheduled(pdf, pdf_link_objnum(p))) + pdf_link_objnum(p) = pdf_new_objnum(pdf); + push_link_level(pdf, p); + alt_rule.wd = width(p); + alt_rule.ht = height(p); + alt_rule.dp = depth(p); + set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_link_margin); + obj_annot_ptr(pdf, pdf_link_objnum(p)) = p; /* the reference for the pdf annot object must be set here */ + addto_page_resources(pdf, obj_type_link, pdf_link_objnum(p)); +} + +@ @c +void end_link(PDF pdf, halfword p) +{ + halfword q; + scaledpos pos = pdf->posstruct->pos; + if (type(p) == vlist_node) + pdf_error("ext4", "\\pdfendlink ended up in vlist"); + if (pdf->link_stack_ptr < 1) + pdf_error("ext4", + "pdf link_stack empty, \\pdfendlink used without \\pdfstartlink?"); + if (pdf->link_stack[pdf->link_stack_ptr].nesting_level != cur_s) + pdf_error("ext4", + "\\pdfendlink ended up in different nesting level than \\pdfstartlink"); + + /* N.B.: test for running link must be done on |link_node| and not |ref_link_node|, + as |ref_link_node| can be set by |do_link| or |append_link| already */ + + if (is_running(width(pdf->link_stack[pdf->link_stack_ptr].link_node))) { + q = pdf->link_stack[pdf->link_stack_ptr].ref_link_node; + if (is_shipping_page && matrixused()) { + matrixrecalculate(pos.h + pdf_link_margin); + pdf_ann_left(q) = getllx() - pdf_link_margin; + pdf_ann_top(q) = cur_page_size.v - getury() - pdf_link_margin; + pdf_ann_right(q) = geturx() + pdf_link_margin; + pdf_ann_bottom(q) = cur_page_size.v - getlly() + pdf_link_margin; + } else { + switch (pdf->posstruct->dir) { + case dir_TLT: + pdf_ann_right(q) = pos.h + pdf_link_margin; + break; + case dir_TRT: + pdf_ann_left(q) = pos.h - pdf_link_margin; + break; + case dir_LTL: + case dir_RTT: + pdf_ann_bottom(q) = pos.v - pdf_link_margin; + break; + } + } + } + pop_link_level(pdf); +} + + +@ For ``running'' annotations we must append a new node when the end of +annotation is in other box than its start. The new created node is identical to +corresponding whatsit node representing the start of annotation, but its +|info| field is |max_halfword|. We set |info| field just before destroying the +node, in order to use |flush_node_list| to do the job. + + +@ Append a new pdf annot to |pdf_link_list| + +@c +void append_link(PDF pdf, halfword parent_box, scaledpos cur, small_number i) +{ + halfword p; + scaled_whd alt_rule; + assert(type(parent_box) == hlist_node); + p = copy_node(pdf->link_stack[(int) i].link_node); + pdf->link_stack[(int) i].ref_link_node = p; + subtype(p) = pdf_link_data_node; /* this node is not a normal link node */ + alt_rule.wd = width(p); + alt_rule.ht = height(p); + alt_rule.dp = depth(p); + set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_link_margin); + pdf_create_obj(pdf, obj_type_others, 0); + obj_annot_ptr(pdf, pdf->obj_ptr) = p; + addto_page_resources(pdf, obj_type_link, pdf->obj_ptr); +} + +@ @c +void scan_startlink(PDF pdf) +{ + int k; + halfword r; + if (abs(cur_list.mode_field) == vmode) + pdf_error("ext1", "\\pdfstartlink cannot be used in vertical mode"); + k = pdf_new_objnum(pdf); + new_annot_whatsit(pdf_start_link_node); + set_pdf_link_attr(cur_list.tail_field, null); + if (scan_keyword("attr")) { + scan_pdf_ext_toks(); + set_pdf_link_attr(cur_list.tail_field, def_ref); + } + r = scan_action(pdf); + set_pdf_link_action(cur_list.tail_field, r); + set_pdf_link_objnum(cur_list.tail_field, k); + pdf_last_link = k; + /* N.B.: although it is possible to set |obj_annot_ptr(k) := tail| here, it + is not safe if nodes are later copied/destroyed/moved; a better place + to do this is inside |do_link|, when the whatsit node is written out */ +} |