diff options
author | Karl Berry <karl@freefriends.org> | 2017-09-14 21:07:39 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2017-09-14 21:07:39 +0000 |
commit | a6b5829b28e31661ed47531b08a01cb2864b290b (patch) | |
tree | d9f792f90aab003d82fcdd2ff3d4b01d30820818 /Master/texmf-dist/tex | |
parent | bf209a8e0ec3db9f1fd8513bdc7341357468a1c0 (diff) |
ocgx2 (14sep17)
git-svn-id: svn://tug.org/texlive/trunk@45303 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty | 256 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty | 389 |
2 files changed, 357 insertions, 288 deletions
diff --git a/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty b/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty index ec2b8b9393a..9dfe301840f 100644 --- a/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty +++ b/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty @@ -40,11 +40,13 @@ % % -------- % -% \ocgbase_add_to_order_list:n -% \ocgbase@add@to@order@list (LaTeX2e version) -% #1: PDF object ID of OCG -% Only OCGs added to the global `Order' list using this command will show -% up in the Layers Tab +% \ocgbase_tree_node_begin:n +% \ocgbase_tree_node_end: +% \ocgbase@tree@node@begin (LaTeX2e versions) +% \ocgbase@tree@node@end +% #1: OCG PDF object +% macro pair (begin and end) for inserting OCG object and its children +% into Order hierarchy (shown as tree structure in the viewers `Layers' tab % % -------- % @@ -82,12 +84,10 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % This work may be distributed and/or modified under the -% conditions of the LaTeX Project Public License, either version 1.3 -% of this license or (at your option) any later version. +% conditions of the LaTeX Project Public License. +% % The latest version of this license is in -% http://mirrors.ctan.org/help/Catalogue/licenses.lppl.html -% and version 1.3 or later is part of all distributions of LaTeX -% version 2005/12/01 or later. +% http://mirrors.ctan.org/macros/latex/base/lppl.txt % % This work has the LPPL maintenance status `maintained'. % @@ -96,8 +96,8 @@ \RequirePackage{expl3} \RequirePackage{pdfbase} -\def\g@ocgbase@date@tl{2017/03/30} -\def\g@ocgbase@version@tl{0.10} +\def\g@ocgbase@date@tl{2017/09/14} +\def\g@ocgbase@version@tl{0.11} \ProvidesExplPackage{ocgbase}{\g@ocgbase@date@tl}{\g@ocgbase@version@tl} {support package for ocgx2.sty} @@ -114,7 +114,6 @@ } \tl_new:N\g_ocgbase_ocgs_tl %takes ocg object refs -\seq_new:N\g_ocgbase_ocgorder_seq \seq_new:N\g_ocgbase_offocgs_seq \pbs_at_end_dvi:n{ @@ -130,77 +129,28 @@ } %global Order list \tl_new:N\l_ocgbase_ocgorderentry_tl - \seq_if_empty:NF\g_ocgbase_ocgorder_seq{ - %process radio button groups in the Order array - \seq_map_inline:Nn\g_ocgbase_ocgorder_seq{ - \cs_if_exist:cT{g_ocgbase_#1_rbtn_order_seq}{ - \int_compare:nTF{\seq_count:c{g_ocgbase_#1_rbtn_groups_seq}>\c_one}{ - \int_compare:nT{\seq_count:c{g_ocgbase_#1_rbtn_order_seq}>\c_zero}{ - %remove all occurrences in Order array outside current rbtn group - \seq_map_inline:cn{g_ocgbase_#1_rbtn_order_seq}{ - \seq_gremove_all:Nn\g_ocgbase_ocgorder_seq{##1} - } - } - }{ - %ignore single-item radio button groups - \seq_gremove_all:Nn\g_ocgbase_ocgorder_seq{#1} - } - } - } - %second sweep on Order array to generate the final Order entry - \tl_new:N\l_ocgbase_ocgorder_tl - \tl_set:Nn\l_ocgbase_order_item_count_tl{0} - \seq_map_inline:Nn\g_ocgbase_ocgorder_seq{ - \tl_set:Nx\l_ocgbase_order_item_count_tl{ - \int_eval:n{\l_ocgbase_order_item_count_tl+\c_one} - } - \cs_if_exist:cTF{g_ocgbase_#1_rbtn_order_seq}{ - \int_compare:nT{\seq_count:c{g_ocgbase_#1_rbtn_order_seq}>\c_zero}{ - \tl_put_right:Nx\l_ocgbase_ocgorder_tl{ - ~[(#1)~\seq_use:cn{g_ocgbase_#1_rbtn_order_seq}{~}] - } - } - }{ - %ordinary (non-radiobutton group) item (ocg obj ref, `[' or `]'), - \tl_set:Nx\l_ocgbase_current_order_item_tl{#1} - \tl_set:Nx\l_ocgbase_next_order_item_tl{ - \seq_item:Nn\g_ocgbase_ocgorder_seq{ - \l_ocgbase_order_item_count_tl+\c_one - } - } - \tl_set:Nx\l_ocgbase_prev_order_item_tl{ - \seq_item:Nn\g_ocgbase_ocgorder_seq{ - \l_ocgbase_order_item_count_tl-\c_one - } - } - \bool_if:nF{ %avoid empty nesting groups - \str_if_eq_p:Vn\l_ocgbase_current_order_item_tl{[} && - \str_if_eq_p:Vn\l_ocgbase_next_order_item_tl{]} - || - \str_if_eq_p:Vn\l_ocgbase_current_order_item_tl{]} && - \str_if_eq_p:Vn\l_ocgbase_prev_order_item_tl{[} - }{\tl_put_right:Nn\l_ocgbase_ocgorder_tl{~#1}} - } - } - \tl_if_empty:NF\l_ocgbase_ocgorder_tl{ - \pbs_pdfobj:nnn{}{array}{\l_ocgbase_ocgorder_tl} - \tl_set:Nx\l_ocgbase_ocgorderentry_tl{/Order~\pbs_pdflastobj:} + \tl_new:N\l_ocgbase_ocgorder_tl + \tl_if_exist:cT{g_ocgbase_nd_0_chld_tl}{ + \ocgbase_build_order:Nn\l_ocgbase_ocgorder_tl{ + \tl_use:c{g_ocgbase_nd_0_chld_tl} } } + \tl_if_empty:NF\l_ocgbase_ocgorder_tl{ + \pbs_pdfobj:nnn{}{array}{\l_ocgbase_ocgorder_tl} + \tl_set:Nx\l_ocgbase_ocgorderentry_tl{/Order~\pbs_pdflastobj:} + } %generate RBGroups entry (radio button groups) - \tl_new:N\l_ocgbase_rbgroups_tl - \seq_map_inline:Nn\g_ocgbase_ocgorder_seq{ - \cs_if_exist:cT{g_ocgbase_#1_rbtn_groups_seq}{ - \int_compare:nT{\seq_count:c{g_ocgbase_#1_rbtn_groups_seq}>\c_one}{ - \tl_put_right:Nx\l_ocgbase_rbgroups_tl{ - ~[\seq_use:cn{g_ocgbase_#1_rbtn_groups_seq}{~}] - } + \tl_new:N\l_ocgbase_rbtn_groups_tl + \seq_map_inline:Nn\g_ocgbase_rbtn_groups_seq{ + \int_compare:nT{\seq_count:c{g_ocgbase_rbtn_group_#1_seq}>\c_one}{ + \tl_put_right:Nx\l_ocgbase_rbtn_groups_tl{ + ~[\seq_use:cn{g_ocgbase_rbtn_group_#1_seq}{~}] } } } \tl_new:N\l_ocgbase_rbgroupsentry_tl - \tl_if_empty:NF\l_ocgbase_rbgroups_tl{ - \pbs_pdfobj:nnn{}{array}{\l_ocgbase_rbgroups_tl} + \tl_if_empty:NF\l_ocgbase_rbtn_groups_tl{ + \pbs_pdfobj:nnn{}{array}{\l_ocgbase_rbtn_groups_tl} \tl_set:Nx\l_ocgbase_rbgroupsentry_tl{/RBGroups~\pbs_pdflastobj:} } \pbs_pdfcatalog:n{ @@ -241,10 +191,98 @@ \cs_new_nopar:Nn\ocgbase_last_ocg:{\g_ocgbase_last_ocg_tl} -%macro for appending OCG object to global `Order' list -% in Layers Tab of the GUI -\cs_new_nopar:Nn\ocgbase_add_to_order_list:n{ - \seq_gput_right:Nx\g_ocgbase_ocgorder_seq{#1} +\int_new:N\g_ocgbase_nd_int %node id +\seq_new:N\g_ocgbase_tree_nd_stack_seq %stack with open ocg node id +\seq_new:N\g_ocgbase_tree_ocg_stack_seq %stack with open ocg obj number +\seq_gpush:Nn\g_ocgbase_tree_nd_stack_seq{0} %push root node +\seq_gpush:Nn\g_ocgbase_tree_ocg_stack_seq{null} %push root node + +%macro for starting OCG object (and nested children) insertion into Order +%hierarchy (shown as tree structure in the viewers `Layers' tab +\cs_new:Nn\ocgbase_tree_node_begin:n{ % #1: OCG obj + %get the parent node from stack + \seq_get:NN\g_ocgbase_tree_nd_stack_seq\l__ocgbase_prnt_tl + \tl_if_exist:cTF{g_ocgbase_nd_\l__ocgbase_prnt_tl _chld_tl}{ + %parent has >=1 children (i. e. my older siblings), traverse them + \tl_set:Nv\l__ocgbase_prev_sbl_tl{g_ocgbase_nd_\l__ocgbase_prnt_tl _chld_tl} + \tl_set:Nx\l__ocgbase_cur_ocg_tl{#1} + \ocgbase_traverse_siblings:NN\l__ocgbase_prev_sbl_tl\l__ocgbase_cur_ocg_tl + \str_if_empty:NTF\l__ocgbase_cur_ocg_tl{ + %I am the first child of my parent to refer to OCG #1 + \int_gincr:N\g_ocgbase_nd_int + \tl_set:Nx\l__ocgbase_cur_nd_tl{\int_use:N\g_ocgbase_nd_int} + %set myself as my next-older sibling's `next sibling' + \tl_gset:cV{ + g_ocgbase_nd_\l__ocgbase_prev_sbl_tl _sbl_tl}\l__ocgbase_cur_nd_tl + }{ + %there is already a sibling referring to OCG #1; no new node needs be + %created + \tl_set:NV\l__ocgbase_cur_nd_tl\l__ocgbase_prev_sbl_tl + } + }{ + %I am the very first child of my parent + \int_gincr:N\g_ocgbase_nd_int + \tl_set:Nx\l__ocgbase_cur_nd_tl{\int_use:N\g_ocgbase_nd_int} + %set myself as my parent's first child + \tl_gset:cV{g_ocgbase_nd_\l__ocgbase_prnt_tl _chld_tl}\l__ocgbase_cur_nd_tl + } + %set the OCG I am referring to + \tl_gset:cx{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _ocg_tl}{#1} + %push current node and its associated OCG obj on the stacks + \seq_gpush:NV\g_ocgbase_tree_nd_stack_seq\l__ocgbase_cur_nd_tl + \seq_gpush:Nx\g_ocgbase_tree_ocg_stack_seq{#1} +} + +%macro that ends insertion of OCG and sub-OCGs into Order tree +\cs_new:Nn\ocgbase_tree_node_end:{ + \seq_get:NN\g_ocgbase_tree_nd_stack_seq\l_tempa_tl + \seq_get:NN\g_ocgbase_tree_ocg_stack_seq\l_tempb_tl + \str_if_eq_x:nnT{ + \cs_if_exist_use:c{g_ocgbase_nd_\l_tempa_tl _ocg_tl} + }{ + \l_tempb_tl + }{ + \seq_gpop:NN\g_ocgbase_tree_nd_stack_seq\g_trash_tl + \seq_gpop:NN\g_ocgbase_tree_ocg_stack_seq\g_trash_tl + } +} + +% helper macro; traverses siblings to find either +% the node which refers to the same OCG (arg #2 remains un-modified), or +% the last sibling inserted (arg #2 is cleared); +% the node id of the sibling found is returned in arg #1 +\cs_new:Nn\ocgbase_traverse_siblings:NN{ + % #1: current node (in/out), #2: OCG obj (in/out) + \str_if_eq_x:nnF{#2}{\tl_use:c{g_ocgbase_nd_#1_ocg_tl}}{ + \tl_if_exist:cTF{g_ocgbase_nd_#1_sbl_tl}{ + \tl_set:Nv#1{g_ocgbase_nd_#1_sbl_tl} + \ocgbase_traverse_siblings:NN#1#2 + }{ + \tl_clear:N#2 + } + } +} + +\cs_new:Nn\ocgbase_build_order:Nn{ + % #1: tl var to which the OCG order is written (output) + % #2: starting node id (input; usually `1') + \tl_set:Nx\l__ocgbase_cur_nd_tl{#2} + % first, append the OCG obj the current node is referring to + \tl_put_right:Nx#1{~\tl_use:c{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _ocg_tl}} + % second, traverse the tree starting with the first child node + \tl_if_exist:cT{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _chld_tl}{ + \seq_gpush:NV\g_ocgbase_tree_nd_stack_seq\l__ocgbase_cur_nd_tl + \tl_put_right:Nn#1{~[} + \ocgbase_build_order:Nn#1{ + \tl_use:c{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _chld_tl}} + \tl_put_right:Nn#1{~]} + \seq_gpop:NN\g_ocgbase_tree_nd_stack_seq\l__ocgbase_cur_nd_tl + } + % third, traverse the tree starting with the next sibling node + \tl_if_exist:cT{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _sbl_tl}{ + \ocgbase_build_order:Nn#1{ + \tl_use:c{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _sbl_tl}} + } } %macro for appending an OCG object to the global `OFF' list @@ -265,31 +303,17 @@ \cs_set_eq:NN\ocgbase_seq_gremove_all:Nn\seq_gremove_all:Nn \cs_generate_variant:Nn\ocgbase_seq_gremove_all:Nn{Nx} -\cs_new_nopar:Nn\ocgbase_add_ocg_to_radiobtn_grp:nnn{ +\seq_new:N\g_ocgbase_rbtn_groups_seq +\cs_new_nopar:Nn\ocgbase_add_ocg_to_radiobtn_grp:nn{ % #1: rbtn group name, - % #2: OCG obj ref, - % #3: visible in Layers Tab - \seq_if_in:NxF\g_ocgbase_ocgorder_seq{#1}{ - \seq_gput_right:Nx\g_ocgbase_ocgorder_seq{#1} - \seq_new:c{g_ocgbase_#1_rbtn_order_seq} - \seq_new:c{g_ocgbase_#1_rbtn_groups_seq} + % #2: OCG obj ref + \seq_if_exist:cF{g_ocgbase_rbtn_group_#1_seq}{ + \seq_new:c{g_ocgbase_rbtn_group_#1_seq} + \seq_gput_right:Nx\g_ocgbase_rbtn_groups_seq{#1} } - \seq_if_in:cxTF{g_ocgbase_#1_rbtn_order_seq}{#2}{ - \bool_if:nT{ - \str_if_eq_x_p:nn{#3}{0} || - \str_if_eq_x_p:nn{#3}{false} - }{ - \ocgbase_seq_gremove_all:cx{g_ocgbase_#1_rbtn_order_seq}{#2} - } - }{ - \bool_if:nF{ - \str_if_eq_x_p:nn{#3}{0} || - \str_if_eq_x_p:nn{#3}{false} - }{ - \seq_gput_right:cx{g_ocgbase_#1_rbtn_order_seq}{#2} - } + \seq_if_in:cxF{g_ocgbase_rbtn_group_#1_seq}{#2}{ + \seq_gput_right:cx{g_ocgbase_rbtn_group_#1_seq}{#2} } - \seq_gput_right:cx{g_ocgbase_#1_rbtn_groups_seq}{#2} } % OC-marked content @@ -297,34 +321,32 @@ \cs_new_nopar:Nn\ocgbase_oc_emc:{\pbs_pdfemc:} %stack of PDF obj references of currently open OCGs -\seq_new:N\g_ocgbase_ocgstack_seq +\seq_new:N\g_ocgbase_open_stack_seq %push OCG to stack -\cs_new_nopar:Nn\ocgbase_ocgstack_push:n{ - \seq_gpush:Nx\g_ocgbase_ocgstack_seq{#1}} +\cs_new_nopar:Nn\ocgbase_open_stack_push:n{ + \seq_gpush:Nx\g_ocgbase_open_stack_seq{#1}} %pop OCG from stack into tl -\cs_new_nopar:Nn\ocgbase_ocgstack_pop:N{\seq_gpop:NN\g_ocgbase_ocgstack_seq#1} -%get top OCG on stack, without removing it -\cs_new_nopar:Nn\ocgbase_ocgstack_top:{ - \seq_item:Nn\g_ocgbase_ocgstack_seq{\c_one}} +\cs_new_nopar:Nn\ocgbase_open_stack_pop:N{ + \seq_gpop:NN\g_ocgbase_open_stack_seq#1} %command that inserts /OC <<OCMD with currently open OCGs>> entry; %for use within annotation/xobject dicts \cs_new_nopar:Nn\ocgbase_insert_oc:{ - \seq_if_empty:NF\g_ocgbase_ocgstack_seq{ - /OC~<</Type/OCMD/OCGs~[\seq_use:Nn\g_ocgbase_ocgstack_seq{~}]/P/AllOn>> + \seq_if_empty:NF\g_ocgbase_open_stack_seq{ + /OC~<</Type/OCMD/OCGs~[\seq_use:Nn\g_ocgbase_open_stack_seq{~}]/P/AllOn>> } } %l2e versions \cs_gset_eq:NN\ocgbase@new@ocg\ocgbase_new_ocg:nnn \cs_gset_eq:NN\ocgbase@last@ocg\ocgbase_last_ocg: -\cs_gset_eq:NN\ocgbase@add@to@order@list\ocgbase_add_to_order_list:n +\cs_gset_eq:NN\ocgbase@tree@node@begin\ocgbase_tree_node_begin:n +\cs_gset_eq:NN\ocgbase@tree@node@end\ocgbase_tree_node_end: \cs_gset_eq:NN\ocgbase@add@to@off@list\ocgbase_add_to_off_list:n \cs_gset_eq:NN\ocgbase@del@from@off@list\ocgbase_del_from_off_list:n -\cs_gset_eq:NN\ocgbase@add@ocg@to@radiobtn@grp\ocgbase_add_ocg_to_radiobtn_grp:nnn +\cs_gset_eq:NN\ocgbase@add@ocg@to@radiobtn@grp\ocgbase_add_ocg_to_radiobtn_grp:nn \cs_gset_eq:NN\ocgbase@oc@bdc\ocgbase_oc_bdc:n \cs_gset_eq:NN\ocgbase@oc@emc\ocgbase_oc_emc: \cs_gset_eq:NN\ocgbase@insert@oc\ocgbase_insert_oc: -\cs_gset_eq:NN\ocgbase@ocgstack@top\ocgbase_ocgstack_top: -\cs_gset_eq:NN\ocgbase@ocgstack@pop\ocgbase_ocgstack_pop:N -\cs_gset_eq:NN\ocgbase@ocgstack@push\ocgbase_ocgstack_push:n +\cs_gset_eq:NN\ocgbase@open@stack@pop\ocgbase_open_stack_pop:N +\cs_gset_eq:NN\ocgbase@open@stack@push\ocgbase_open_stack_push:n diff --git a/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty b/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty index 1bd15ab8f42..51958260364 100644 --- a/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty +++ b/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty @@ -23,12 +23,10 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % This work may be distributed and/or modified under the -% conditions of the LaTeX Project Public License, either version 1.3 -% of this license or (at your option) any later version. +% conditions of the LaTeX Project Public License. +% % The latest version of this license is in -% http://mirrors.ctan.org/help/Catalogue/licenses.lppl.html -% and version 1.3 or later is part of all distributions of LaTeX -% version 2005/12/01 or later. +% http://mirrors.ctan.org/macros/latex/base/lppl.txt % % This work has the LPPL maintenance status `maintained'. % @@ -37,8 +35,8 @@ \RequirePackage{xparse} \RequirePackage{l3keys2e} -\def\g@ocgxii@date@tl{2017/06/08} -\def\g@ocgxii@version@tl{0.29} +\def\g@ocgxii@date@tl{2017/09/14} +\def\g@ocgxii@version@tl{0.30} \ProvidesExplPackage{ocgx2}{\g@ocgxii@date@tl}{\g@ocgxii@version@tl} {ports `ocgx' functionality to dvips+ps2pdf, xelatex and dvipdfmx} @@ -67,6 +65,11 @@ to~the~preamble~of~your~document. } +\msg_set:nnn{ocgx2}{beamer~and~ocgcolorlinks}{ + Option~`ocgcolorlinks'~cannot~be~used~with~class~Beamer.\\\\ + Using~`colorlinks'~instead. +} + %package opts %unknown package option error message \msg_set:nnnn{ocgx2}{unknown~package~option}{Unknown~package~option~`#1'.}{ @@ -77,6 +80,8 @@ \bool_new:N\g_ocgxii_dvipdfmx_bool \bool_new:N\l_ocgxii_tikz_bool \bool_new:N\l_ocgxii_ocgcolorlinks_bool +\bool_new:N\g_ocgxii_showingui_bool +\bool_new:N\l_ocgxii_showingui_bool \keys_define:nn{ocgx2}{ xetex .code:n = { @@ -112,13 +117,20 @@ exportocg / ifvisible .code:n={\tl_gclear_new:N\g_ocgxii_export_tl}, exportocg .default:n={ifvisible}, - listintoolbar .choices:nn = {always,never,iffirstuse}{ - \tl_gset:Nx\g_ocgxii_listno_tl{\int_eval:n{\l_keys_choice_int-\c_one}} + showingui .choices:nn = {true,false,always,never,iffirstuse}{ + \bool_if:nTF{ + \str_if_eq_x_p:nn{#1}{false} || + \str_if_eq_x_p:nn{#1}{never} + }{ + \bool_gset_false:N\g_ocgxii_showingui_bool + }{ + \bool_gset_true:N\g_ocgxii_showingui_bool + } }, - listintoolbar .default:n={iffirstuse}, + showingui .default:n={true}, - showingui .meta:n = {listintoolbar=#1}, - showingui .default:n={iffirstuse}, + listintoolbar .meta:n = {showingui=#1}, + listintoolbar .default:n={true}, tikz .bool_set:N = \l_ocgxii_tikz_bool, tikz .default:n = true, @@ -148,23 +160,12 @@ } \cs_new_nopar:Nn\ocgxii_beginocg:nnnn{ - \bool_if:NT\g_ocgxii_nestedB_bool{ - \seq_gput_left:Nx\g_ocgxii_nested_seq{\ocgbase_ocgstack_top:} - \ocgbase_add_to_order_list:n{[} - } - \bool_gset_true:N\g_ocgxii_nestedB_bool - \bool_gset_false:N\g_ocgxii_nestedE_bool \group_begin: \ocgxii_reset_cmd_opts: % ... to the user-set package options \tl_if_exist:cTF{ocgxii@#3}{ %re-open existing layer \tl_set:Nx\l_tempa_tl{\tl_use:c{ocgxii@#3.opts},#1} \tl_gset:cx{ocgxii@#3.opts}{\l_tempa_tl} %new options appended \keys_set:nV{ocgx2/user}\l_tempa_tl - \int_compare:nTF{\l_ocgxii_listno_tl=\c_zero}{ - \ocgbase_add_to_order_list:n{\tl_use:c{ocgxii@#3}} - }{ - \bool_gset_false:N\g_ocgxii_nestedB_bool - } \bool_if:nTF{ %initial visibility \str_if_eq_x_p:nn{#4}{1} || \str_if_eq_x_p:nn{#4}{on} || @@ -182,20 +183,10 @@ \l_ocgxii_view_tl\l_ocgxii_print_tl\l_ocgxii_export_tl }{#4} \tl_gset:cx{ocgxii@#3}{\ocgbase_last_ocg:} - \int_compare:nTF{\l_ocgxii_listno_tl=\c_one}{ - \bool_gset_false:N\g_ocgxii_nestedB_bool - }{ - \ocgbase_add_to_order_list:n{\ocgbase_last_ocg:} - } \iow_now:Nx\@mainaux{ \token_to_str:N\ocgxii@newkey{ocgx2.ocg.#3}{\ocgbase_last_ocg:} } } - \seq_map_inline:Nn\l_ocgxii_rbgrps_seq{% process list of radio btn groups - \ocgbase_add_ocg_to_radiobtn_grp:nnn{##1}{\tl_use:c{ocgxii@#3}}{ - \int_compare:nTF{\l_ocgxii_listno_tl=\c_one}{false}{true} - } - } \bool_if:nT{ !\cs_if_exist:cTF{ocgx2.ocg.#3}{ \str_if_eq_x_p:nn{\tl_use:c{ocgx2.ocg.#3}}{\tl_use:c{ocgxii@#3}} @@ -209,8 +200,15 @@ } } \tl_gset:cx{ocgx2.ocg.#3}{\tl_use:c{ocgxii@#3}} - \ocgbase_ocgstack_push:n{\tl_use:c{ocgxii@#3}} - \ocgxii_stack_shipout:NN\ocgxii@ocg@stack@on@page\g_ocgbase_ocgstack_seq + \seq_map_inline:Nn\l_ocgxii_rbgrps_seq{% process list of radio btn groups + \ocgbase_add_ocg_to_radiobtn_grp:nn{##1}{\tl_use:c{ocgxii@#3}} + } + \ocgbase_open_stack_push:n{\tl_use:c{ocgxii@#3}} + \ocgxii_stack_shipout:NN\ocgxii@ocg@stack@on@page\g_ocgbase_open_stack_seq + % insert OCG into Order tree + \bool_if:NT\l_ocgxii_showingui_bool{ + \ocgbase_tree_node_begin:n{\tl_use:c{ocgxii@#3}} + } \group_end: \ocgbase_oc_bdc:n{\tl_use:c{ocgxii@#3}} \ignorespaces @@ -219,27 +217,11 @@ \cs_new_nopar:Nn\ocgxii_endocg:{ \unskip \ocgbase_oc_emc: - \bool_if:nT{ - \g_ocgxii_nestedE_bool && - \str_if_eq_x_p:nn{ - \seq_item:Nn\g_ocgxii_nested_seq{\c_one} - }{ - \ocgbase_ocgstack_top: - } - }{ - \ocgbase_add_to_order_list:n{]} - \seq_gpop_left:NN\g_ocgxii_nested_seq\l_trash_tl - } - \ocgbase_ocgstack_pop:N\l_trash_tl - \ocgxii_stack_shipout:NN\ocgxii@ocg@stack@on@page\g_ocgbase_ocgstack_seq - \bool_gset_false:N\g_ocgxii_nestedB_bool - \bool_gset_true:N\g_ocgxii_nestedE_bool + \ocgbase_tree_node_end: + \ocgbase_open_stack_pop:N\l_trash_tl + \ocgxii_stack_shipout:NN\ocgxii@ocg@stack@on@page\g_ocgbase_open_stack_seq } -\bool_new:N\g_ocgxii_nestedB_bool % nested OCG begin -\bool_new:N\g_ocgxii_nestedE_bool % nested OCG end -\seq_new:N\g_ocgxii_nested_seq % for keeping track of parent OCGs - \cs_new_nopar:Nn\ocgxii_stack_shipout:NN{ \iow_shipout_x:Nx\@mainaux{ \token_to_str:N#1{ @@ -414,13 +396,13 @@ \int_new:N\g_ocgxii_widcount_int% widget counter -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % re-implement commands from ocgx.sty (all engines including ps2pdf [gs>=9.15]) -% adding optional `*` (arg 1) -> non-breakable Button Widget & mouse-up trigger -% instead of plain (multiline) Link -% adding optional 2nd argument -> Button Widget with one of various mouse -% triggers -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% adding optional `*` (arg 1) -> non-breakable link instead of plain (multiline) +% Link; +% adding optional 2nd argument -> Button Widget (non-breakable) with one of +% various mouse triggers (`troggerocgs` option from ocg-p) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \DeclareDocumentCommand\switchocg{s o m +m}{ \ocgxii_actionsocg:nnnnnn{#1}{#2}{#3}{}{}{#4} } @@ -437,114 +419,154 @@ \ocgxii_actionsocg:nnnnnn{#1}{#2}{#3}{#4}{#5}{#6} } +\bool_new:N\l_ocgxii_mouse_triggers_bool +\bool_new:N\l_ocgxii_nobreak_bool \cs_new:Nn\ocgxii_actionsocg:nnnnnn{ \leavevmode - \bool_if:nTF{#1 || \IfValueTF{#2}{\c_true_bool}{\c_false_bool}}{ - % implemented as Widget annot (non-breakable) - \ocgxii_ocglist_process_idlist:nn{ - \IfValueTF{#2}{#2}{triggerocg=onmouseup} - }{#3} - \tl_set_eq:NN\l_ocgxii_toswitch_e_tl\l_ocgxii_e_list_tl - \tl_set_eq:NN\l_ocgxii_toswitch_x_tl\l_ocgxii_x_list_tl - \tl_set_eq:NN\l_ocgxii_toswitch_d_tl\l_ocgxii_d_list_tl - \tl_set_eq:NN\l_ocgxii_toswitch_u_tl\l_ocgxii_u_list_tl - \ocgxii_ocglist_process_idlist:nn{ - \IfValueTF{#2}{#2}{triggerocg=onmouseup} - }{#4} - \tl_set_eq:NN\l_ocgxii_toshow_e_tl\l_ocgxii_e_list_tl - \tl_set_eq:NN\l_ocgxii_toshow_x_tl\l_ocgxii_x_list_tl - \tl_set_eq:NN\l_ocgxii_toshow_d_tl\l_ocgxii_d_list_tl - \tl_set_eq:NN\l_ocgxii_toshow_u_tl\l_ocgxii_u_list_tl - \ocgxii_ocglist_process_idlist:nn{ - \IfValueTF{#2}{#2}{triggerocg=onmouseup} - }{#5} - \tl_set_eq:NN\l_ocgxii_tohide_e_tl\l_ocgxii_e_list_tl - \tl_set_eq:NN\l_ocgxii_tohide_x_tl\l_ocgxii_x_list_tl - \tl_set_eq:NN\l_ocgxii_tohide_d_tl\l_ocgxii_d_list_tl - \tl_set_eq:NN\l_ocgxii_tohide_u_tl\l_ocgxii_u_list_tl + \bool_set_false:N\l_ocgxii_mouse_triggers_bool + \bool_set_false:N\l_ocgxii_nobreak_bool + % explicitly non-breakable? + \bool_if:nT{#1}{\bool_set_true:N\l_ocgxii_nobreak_bool} + % + %clear actions for various mouse triggers (e,d,x) + \tl_clear:N\l_ocgxii_toswitch_e_tl + \tl_clear:N\l_ocgxii_toswitch_x_tl + \tl_clear:N\l_ocgxii_toswitch_d_tl + \tl_clear:N\l_ocgxii_toshow_e_tl + \tl_clear:N\l_ocgxii_toshow_x_tl + \tl_clear:N\l_ocgxii_toshow_d_tl + \tl_clear:N\l_ocgxii_tohide_e_tl + \tl_clear:N\l_ocgxii_tohide_x_tl + \tl_clear:N\l_ocgxii_tohide_d_tl + % + %process *all* mouse triggers (e,d,u,x) + \ocgxii_ocglist_process_idlist:nn{ + \IfValueTF{#2}{#2}{triggerocg=onmouseup} + }{#3} + \tl_set_eq:NN\l_ocgxii_toswitch_e_tl\l_ocgxii_e_list_tl + \tl_set_eq:NN\l_ocgxii_toswitch_x_tl\l_ocgxii_x_list_tl + \tl_set_eq:NN\l_ocgxii_toswitch_d_tl\l_ocgxii_d_list_tl + \tl_set_eq:NN\l_ocgxii_toswitch_u_tl\l_ocgxii_u_list_tl + \ocgxii_ocglist_process_idlist:nn{ + \IfValueTF{#2}{#2}{triggerocg=onmouseup} + }{#4} + \tl_set_eq:NN\l_ocgxii_toshow_e_tl\l_ocgxii_e_list_tl + \tl_set_eq:NN\l_ocgxii_toshow_x_tl\l_ocgxii_x_list_tl + \tl_set_eq:NN\l_ocgxii_toshow_d_tl\l_ocgxii_d_list_tl + \tl_set_eq:NN\l_ocgxii_toshow_u_tl\l_ocgxii_u_list_tl + \ocgxii_ocglist_process_idlist:nn{ + \IfValueTF{#2}{#2}{triggerocg=onmouseup} + }{#5} + \tl_set_eq:NN\l_ocgxii_tohide_e_tl\l_ocgxii_e_list_tl + \tl_set_eq:NN\l_ocgxii_tohide_x_tl\l_ocgxii_x_list_tl + \tl_set_eq:NN\l_ocgxii_tohide_d_tl\l_ocgxii_d_list_tl + \tl_set_eq:NN\l_ocgxii_tohide_u_tl\l_ocgxii_u_list_tl + %any triggers apart from mouse-up? + \str_if_eq_x:nnF{ + \l_ocgxii_toswitch_e_tl\l_ocgxii_toswitch_x_tl\l_ocgxii_toswitch_d_tl + \l_ocgxii_toshow_e_tl\l_ocgxii_toshow_x_tl\l_ocgxii_toshow_d_tl + \l_ocgxii_tohide_e_tl\l_ocgxii_tohide_x_tl\l_ocgxii_tohide_d_tl + }{}{ + \bool_set_true:N\l_ocgxii_mouse_triggers_bool + } + % + \bool_if:nTF{\l_ocgxii_nobreak_bool || \l_ocgxii_mouse_triggers_bool}{ \hbox_set:Nn\l_tmpa_box{#6} \pbs_pdfannot:nnnn{ \dim_use:N\box_wd:N\l_tmpa_box}{ \dim_use:N\box_ht:N\l_tmpa_box}{ \dim_use:N\box_dp:N\l_tmpa_box }{ - /Subtype/Widget/Ff~65536/FT/Btn/BS<</W~0>> + \bool_if:NTF\l_ocgxii_mouse_triggers_bool{ + % e,d,x mouse triggers require (non-breakable) /Widget annot with AA + % (additional actions) dict + /Subtype/Widget/Ff~65536/FT/Btn/BS<</W~0>> + /T~(ocgx2@\int_use:N\g_ocgxii_widcount_int) + /AA << + \str_if_eq_x:nnF{}{ + \l_ocgxii_toswitch_u_tl\l_ocgxii_toshow_u_tl\l_ocgxii_tohide_u_tl + }{ + /U <</S/SetOCGState/State [ + \str_if_eq:VnF\l_ocgxii_toswitch_u_tl{}{ + /Toggle~\l_ocgxii_toswitch_u_tl + } + \str_if_eq:VnF\l_ocgxii_toshow_u_tl{}{ + /ON~\l_ocgxii_toshow_u_tl + } + \str_if_eq:VnF\l_ocgxii_tohide_u_tl{}{ + /OFF~\l_ocgxii_tohide_u_tl + } + ]>> + } + \str_if_eq_x:nnF{}{ + \l_ocgxii_toswitch_d_tl\l_ocgxii_toshow_d_tl\l_ocgxii_tohide_d_tl + }{ + /D <</S/SetOCGState/State [ + \str_if_eq:VnF\l_ocgxii_toswitch_d_tl{}{ + /Toggle~\l_ocgxii_toswitch_d_tl + } + \str_if_eq:VnF\l_ocgxii_toshow_d_tl{}{ + /ON~\l_ocgxii_toshow_d_tl + } + \str_if_eq:VnF\l_ocgxii_tohide_d_tl{}{ + /OFF~\l_ocgxii_tohide_d_tl + } + ]>> + } + \str_if_eq_x:nnF{}{ + \l_ocgxii_toswitch_e_tl\l_ocgxii_toshow_e_tl\l_ocgxii_tohide_e_tl + }{ + /E <</S/SetOCGState/State [ + \str_if_eq:VnF\l_ocgxii_toswitch_e_tl{}{ + /Toggle~\l_ocgxii_toswitch_e_tl + } + \str_if_eq:VnF\l_ocgxii_toshow_e_tl{}{ + /ON~\l_ocgxii_toshow_e_tl + } + \str_if_eq:VnF\l_ocgxii_tohide_e_tl{}{ + /OFF~\l_ocgxii_tohide_e_tl + } + ]>> + } + \str_if_eq_x:nnF{}{ + \l_ocgxii_toswitch_x_tl\l_ocgxii_toshow_x_tl\l_ocgxii_tohide_x_tl + }{ + /X <</S/SetOCGState/State [ + \str_if_eq:VnF\l_ocgxii_toswitch_x_tl{}{ + /Toggle~\l_ocgxii_toswitch_x_tl + } + \str_if_eq:VnF\l_ocgxii_toshow_x_tl{}{ + /ON~\l_ocgxii_toshow_x_tl + } + \str_if_eq:VnF\l_ocgxii_tohide_x_tl{}{ + /OFF~\l_ocgxii_tohide_x_tl + } + ]>> + } + >> + }{ + %mouse-up only only needs annot with /Link subtype + /Subtype/Link + /A <</S/SetOCGState + /State [ + \str_if_eq:VnF{\l_ocgxii_toswitch_u_tl}{}{ + /Toggle~\l_ocgxii_toswitch_u_tl}~ + \str_if_eq:VnF{\l_ocgxii_toshow_u_tl}{}{/ON~\l_ocgxii_toshow_u_tl}~ + \str_if_eq:VnF{\l_ocgxii_tohide_u_tl}{}{/OFF~\l_ocgxii_tohide_u_tl} + ] + >> + /Border~[0~0~0] + } \cs_if_exist:NT\@pdfhighlight{ \ifx\@pdfhighlight\@empty\else/H\@pdfhighlight\fi } - /T~(ocgx2@\int_use:N\g_ocgxii_widcount_int) - /AA << - \str_if_eq_x:nnF{}{ - \l_ocgxii_toswitch_u_tl\l_ocgxii_toshow_u_tl\l_ocgxii_tohide_u_tl - }{ - /U <</S/SetOCGState/State [ - \str_if_eq:VnF\l_ocgxii_toswitch_u_tl{}{ - /Toggle~\l_ocgxii_toswitch_u_tl - } - \str_if_eq:VnF\l_ocgxii_toshow_u_tl{}{ - /ON~\l_ocgxii_toshow_u_tl - } - \str_if_eq:VnF\l_ocgxii_tohide_u_tl{}{ - /OFF~\l_ocgxii_tohide_u_tl - } - ]>> - } - \str_if_eq_x:nnF{}{ - \l_ocgxii_toswitch_d_tl\l_ocgxii_toshow_d_tl\l_ocgxii_tohide_d_tl - }{ - /D <</S/SetOCGState/State [ - \str_if_eq:VnF\l_ocgxii_toswitch_d_tl{}{ - /Toggle~\l_ocgxii_toswitch_d_tl - } - \str_if_eq:VnF\l_ocgxii_toshow_d_tl{}{ - /ON~\l_ocgxii_toshow_d_tl - } - \str_if_eq:VnF\l_ocgxii_tohide_d_tl{}{ - /OFF~\l_ocgxii_tohide_d_tl - } - ]>> - } - \str_if_eq_x:nnF{}{ - \l_ocgxii_toswitch_e_tl\l_ocgxii_toshow_e_tl\l_ocgxii_tohide_e_tl - }{ - /E <</S/SetOCGState/State [ - \str_if_eq:VnF\l_ocgxii_toswitch_e_tl{}{ - /Toggle~\l_ocgxii_toswitch_e_tl - } - \str_if_eq:VnF\l_ocgxii_toshow_e_tl{}{ - /ON~\l_ocgxii_toshow_e_tl - } - \str_if_eq:VnF\l_ocgxii_tohide_e_tl{}{ - /OFF~\l_ocgxii_tohide_e_tl - } - ]>> - } - \str_if_eq_x:nnF{}{ - \l_ocgxii_toswitch_x_tl\l_ocgxii_toshow_x_tl\l_ocgxii_tohide_x_tl - }{ - /X <</S/SetOCGState/State [ - \str_if_eq:VnF\l_ocgxii_toswitch_x_tl{}{ - /Toggle~\l_ocgxii_toswitch_x_tl - } - \str_if_eq:VnF\l_ocgxii_toshow_x_tl{}{ - /ON~\l_ocgxii_toshow_x_tl - } - \str_if_eq:VnF\l_ocgxii_tohide_x_tl{}{ - /OFF~\l_ocgxii_tohide_x_tl - } - ]>> - } - >> }\box_use_clear:N\l_tmpa_box - \pbs_appendtofields:n{\pbs_pdflastann:} - \int_gincr:N\g_ocgxii_widcount_int + \bool_if:NT\l_ocgxii_mouse_triggers_bool{ + \pbs_appendtofields:n{\pbs_pdflastann:} + \int_gincr:N\g_ocgxii_widcount_int + } }{ - \ocgxii_ocglist_process_idlist:nn{triggerocg=onmouseup}{#3} - \tl_set_eq:NN\l_ocgxii_toswitch_u_tl\l_ocgxii_u_list_tl - \ocgxii_ocglist_process_idlist:nn{triggerocg=onmouseup}{#4} - \tl_set_eq:NN\l_ocgxii_toshow_u_tl\l_ocgxii_u_list_tl - \ocgxii_ocglist_process_idlist:nn{triggerocg=onmouseup}{#5} - \tl_set_eq:NN\l_ocgxii_tohide_u_tl\l_ocgxii_u_list_tl + %line-breakable annotation \pbs_pdflink:nn{ /Subtype/Link /A <</S/SetOCGState @@ -621,16 +643,25 @@ exportocg / ifvisible .code:n={\tl_clear:N\l_ocgxii_export_tl}, exportocg .default:n={ifvisible}, - listintoolbar .choices:nn = {always,never,iffirstuse}{ - \tl_set:Nx\l_ocgxii_listno_tl{\int_eval:n{\l_keys_choice_int-\c_one}} + showingui .choices:nn = {true,false,always,never,iffirstuse}{ + \bool_if:nTF{ + \str_if_eq_x_p:nn{#1}{false} || + \str_if_eq_x_p:nn{#1}{never} + }{ + \bool_set_false:N\l_ocgxii_showingui_bool + }{ + \bool_set_true:N\l_ocgxii_showingui_bool + } }, - listintoolbar .default:n={iffirstuse}, + showingui .default:n={true}, - showingui .meta:n = {listintoolbar=#1}, - showingui .default:n={iffirstuse}, + listintoolbar .meta:n = {showingui=#1}, + listintoolbar .default:n={true}, radiobtngrp .code:n = { - \seq_put_right:Nx\l_ocgxii_rbgrps_seq{#1} + \seq_if_in:NxF\l_ocgxii_rbgrps_seq{#1}{ + \seq_put_right:Nx\l_ocgxii_rbgrps_seq{#1} + } }, radiobtngrp .value_required:n = {true} } @@ -639,7 +670,7 @@ \tl_set_eq:NN\l_ocgxii_view_tl\g_ocgxii_view_tl \tl_set_eq:NN\l_ocgxii_print_tl\g_ocgxii_print_tl \tl_set_eq:NN\l_ocgxii_export_tl\g_ocgxii_export_tl - \tl_set_eq:NN\l_ocgxii_listno_tl\g_ocgxii_listno_tl + \bool_set_eq:NN\l_ocgxii_showingui_bool\g_ocgxii_showingui_bool %stack of radio button group names the current ocg belongs to \seq_clear_new:N\l_ocgxii_rbgrps_seq } @@ -666,15 +697,17 @@ % % with pdftex, luatex, xetex, dvipdfmx drivers % -% based on Ben Lerner's solution +% based on Ben Lerner's idea % http://tex.stackexchange.com/a/104227; % with some improvements %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \sys_if_output_pdf:TF{ \cs_new:Nn\ocgxii_literal_page:n{\pdfliteral~page~{#1}} +% \cs_new:Nn\ocgxii_literal_page:n{\pdfliteral~direct~{#1}} }{ \bool_if:NT\g_ocgxii_dvipdfmx_bool{ %dvipdfmx/XeTeX \cs_new:Nn\ocgxii_literal_page:n{\special{pdf:code~#1}} +% \cs_new:Nn\ocgxii_literal_page:n{\special{pdf:literal~direct~#1}} } } @@ -760,10 +793,15 @@ \ocgxii_literal_page:n{q~7~Tr} } \cs_gset_nopar:Nn\ocgxii_colourlink_end:{ - \vbox_to_zero:n{ - \vss - \hbox_to_zero:n{\skip_horizontal:n{2\paperwidth}.\hss} - \skip_vertical:n{2\paperheight} + %this should keep empty link annots from flooding the page with link + %colour by placing a default glyph (`.') beyond the page limits; + %only works with pdfLaTeX/LuaLaTeX + \sys_if_output_pdf:T{ + \vbox_to_zero:n{ + \vss + \hbox_to_zero:n{\skip_horizontal:n{2\paperwidth}.\hss} + \skip_vertical:n{2\paperheight} + } } \ocgbase_oc_bdc:n{\ocgxii@OCPrint} \ocgxii_literal_page:n{-88888~-88888~99999~99999~re~f} @@ -792,15 +830,24 @@ \seq_get_left:NNT\g_ocgxii_lnk_color_seq\l_tmpa_tl{ \ocgxii_colourlink_nobreak_end: \group_end: - \vbox_to_zero:n{ % avoid mixing up CTM + \sys_if_output_pdf:T{\vbox_to_zero:n{ % avoid mixing up CTM \vss \hbox_to_zero:n{\skip_horizontal:n{2\paperwidth}.\hss} \skip_vertical:n{2\paperheight} - } + }} \ocgxii_colourlink_begin: } } +% option ocgcolorlinks and beamer are not compatible +\bool_if:NT\l_ocgxii_ocgcolorlinks_bool{ + \@ifclassloaded{beamer}{ + \bool_set_false:N\l_ocgxii_ocgcolorlinks_bool + \hypersetup{colorlinks} + \msg_warning:nn{ocgx2}{beamer~and~ocgcolorlinks} + }{} +} + \bool_if:NT\l_ocgxii_ocgcolorlinks_bool{ \@ifpackageloaded{hyperref}{ \Hy@colorlinkstrue @@ -883,7 +930,7 @@ switch ocg with mark on/.style 2 args={ postaction={ path picture={ - \begin{ocg}{#1}{#1}{1} + \begin{ocg}[showingui=false]{#1}{#1}{1} \draw (path picture bounding box.south west) -- @@ -900,7 +947,7 @@ switch ocg with mark off/.style 2 args={ postaction={ path picture={ - \begin{ocg}{#1}{#1}{0} + \begin{ocg}[showingui=false]{#1}{#1}{0} \draw (path picture bounding box.south west) -- |