%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ocgx2.sty % % Copyright 2015--\today, Alexander Grahn % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % The intent of this package is to be a drop-in replacement for the already % existing CTAN package `ocgx' by Paul Gaborit, and also for `ocg-p' and `ocg'. % % It re-implements the functionality of the ocg, ocgx and ocg-p packages % and adds support for all known engines and backends including % latex+dvips+ps2pdf, xelatex, latex+dvipdfmx, lualatex. % % With ocgx2, PDF layers may extend across page breaks. % % Adds some minor improvements, such as package options, remembering option % settings of reopened ocgs, correct behaviour of ocg switching links that were % themselves placed on layers, compatibility with the animate and media9 % packages. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 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. % 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. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is A. Grahn. \RequirePackage{xparse} \RequirePackage{l3keys2e} \def\g@ocgxii@date@tl{2017/06/08} \def\g@ocgxii@version@tl{0.29} \ProvidesExplPackage{ocgx2}{\g@ocgxii@date@tl}{\g@ocgxii@version@tl} {ports `ocgx' functionality to dvips+ps2pdf, xelatex and dvipdfmx} %creating global definitions \cs_new:Npn\ocgxii@newkey#1#2{\tl_gset:cx{#1}{#2}} \AtBeginDocument{ \iow_now:Nx\@mainaux{ \token_to_str:N\providecommand\token_to_str:N\ocgxii@newkey[2]{} } \iow_now:Nx\@mainaux{ \token_to_str:N\providecommand\token_to_str:N\ocgxii@ocg@stack@on@page[2]{} } \iow_now:Nx\@mainaux{ \token_to_str:N\providecommand \token_to_str:N\ocgxii@lnkcol@stack@on@page[2]{} } } \msg_set:nnn{ocgx2}{missing~package}{ Package~`#1'~must~be~loaded~before~ocgx2.\\\\ Put\\\\ \space\space\string\usepackage#2{#1}\\ \space\space\string\usepackage[ocgcolorlinks]{ocgx2}\\\\ to~the~preamble~of~your~document. } %package opts %unknown package option error message \msg_set:nnnn{ocgx2}{unknown~package~option}{Unknown~package~option~`#1'.}{ Package option~'#1'~is~unknown;\\ perhaps~it~is~spelled~incorrectly. } \bool_new:N\g_ocgxii_dvipdfmx_bool \bool_new:N\l_ocgxii_tikz_bool \bool_new:N\l_ocgxii_ocgcolorlinks_bool \keys_define:nn{ocgx2}{ xetex .code:n = { \PassOptionsToPackage{xetex}{pdfbase} }, dvipdfmx .code:n = { \PassOptionsToPackage{dvipdfmx}{pdfbase} \bool_gset_true:N\g_ocgxii_dvipdfmx_bool }, viewocg .choice:, viewocg / always .code:n={ \tl_gset:Nn\g_ocgxii_view_tl{/View<>}}, viewocg / never .code:n={ \tl_gset:Nn\g_ocgxii_view_tl{/View<>}}, viewocg / ifvisible .code:n={\tl_gclear_new:N\g_ocgxii_view_tl}, viewocg .default:n={ifvisible}, printocg .choice:, printocg / always .code:n={ \tl_gset:Nn\g_ocgxii_print_tl{/Print<>}}, printocg / never .code:n={ \tl_gset:Nn\g_ocgxii_print_tl{/Print<>}}, printocg / ifvisible .code:n={\tl_gclear_new:N\g_ocgxii_print_tl}, printocg .default:n={ifvisible}, exportocg .choice:, exportocg / always .code:n={ \tl_gset:Nn\g_ocgxii_export_tl{/Export<>}}, exportocg / never .code:n={ \tl_gset:Nn\g_ocgxii_export_tl{/Export<>}}, 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}} }, listintoolbar .default:n={iffirstuse}, showingui .meta:n = {listintoolbar=#1}, showingui .default:n={iffirstuse}, tikz .bool_set:N = \l_ocgxii_tikz_bool, tikz .default:n = true, ocgcolorlinks .bool_set:N = \l_ocgxii_ocgcolorlinks_bool, ocgcolorlinks .default:n = true, unknown .code:n = { \msg_error:nnx{ocgx2}{unknown~package~option}{\l_keys_key_tl} } } %package options preset \keys_set:nn{ocgx2}{viewocg,printocg,exportocg,showingui,tikz=false} %process package options \ProcessKeysOptions{ocgx2} \sys_if_engine_xetex:T{\bool_gset_true:N\g_ocgxii_dvipdfmx_bool} \RequirePackage{ocgbase} %also loads pdfbase.sty %re-implement ocg-p's `ocg' environment \DeclareDocumentEnvironment{ocg}{O{}mmm}{ \ocgxii_beginocg:nnnn{#1}{#2}{#3}{#4} }{ \ocgxii_endocg: } \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} || \str_if_eq_x_p:nn{#4}{true} }{ \ocgbase_del_from_off_list:n{\tl_use:c{ocgxii@#3}} }{ \ocgbase_add_to_off_list:n{\tl_use:c{ocgxii@#3}} } }{ \tl_set:Nx\l_tempa_tl{#1} \tl_gset:cx{ocgxii@#3.opts}{\l_tempa_tl} \keys_set:nV{ocgx2/user}\l_tempa_tl \ocgbase_new_ocg:nnn{#2}{ \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}} }{ \c_false_bool } }{ \tl_if_exist:NF\g_ocgxii_rerunwarned_tl{ \tl_new:N\g_ocgxii_rerunwarned_tl \AtEndDocument{\msg_warning:nn{ocgx2}{rerun}} } } \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 \group_end: \ocgbase_oc_bdc:n{\tl_use:c{ocgxii@#3}} \ignorespaces } \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 } \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{ \exp_not:N\int_use:N\g_ocgxii_page_int }{\seq_use:Nn#2{,}} } } \cs_new_nopar:Npn\ocgxii@ocg@stack@on@page#1#2{ \seq_gset_from_clist:cn{g_pending_ocgs_on_#1_seq}{#2} %re-add braces around items for dvips \bool_if:nT{\sys_if_output_dvi_p: && !\g_ocgxii_dvipdfmx_bool}{ \seq_map_inline:cn{g_pending_ocgs_on_#1_seq}{ \seq_gpop_left:cN{g_pending_ocgs_on_#1_seq}\l_trash_tl \seq_gput_right:cn{g_pending_ocgs_on_#1_seq}{{##1}} } } } \ocgxii@ocg@stack@on@page{0}{} %initialize \cs_new_nopar:Npn\ocgxii@lnkcol@stack@on@page#1#2{ \seq_gset_from_clist:cn{g_pending_lnkcols_on_#1_seq}{#2} %re-add braces around items \seq_map_inline:cn{g_pending_lnkcols_on_#1_seq}{ \seq_gpop_left:cN{g_pending_lnkcols_on_#1_seq}\l_trash_tl \seq_gput_right:cn{g_pending_lnkcols_on_#1_seq}{{##1}} } } \ocgxii@lnkcol@stack@on@page{0}{} %initialize %end-of-page action \pbs_eop_action:n{ \seq_if_exist:cT{g_pending_lnkcols_on_\int_use:c{g_ocgxii_page_int}_seq}{ %check whether end-of-page link colour stack has settled \iow_shipout:Nx\@mainaux{ \token_to_str:N\ocgxii@newkey{ocgx2.oldlnkcol.\int_use:N\g_ocgxii_page_int}{ \seq_use:cn{g_pending_lnkcols_on_\int_use:c{g_ocgxii_page_int}_seq}{,} } } \bool_if:nT{ !\cs_if_exist:cTF{ocgx2.oldlnkcol.\int_use:N\g_ocgxii_page_int}{ \str_if_eq_x_p:nn{ \tl_use:c{ocgx2.oldlnkcol.\int_use:N\g_ocgxii_page_int} }{ \seq_use:cn{g_pending_lnkcols_on_\int_use:c{g_ocgxii_page_int}_seq}{,} } }{ \c_false_bool } }{ \tl_if_exist:NF\g_ocgxii_rerunwarned_tl{ \tl_new:N\g_ocgxii_rerunwarned_tl \AtEndDocument{\msg_warning:nn{ocgx2}{rerun}} } } % now close the colourlink opened last \seq_get:cNT{g_pending_lnkcols_on_\int_use:c{g_ocgxii_page_int}_seq}\l_tmpa_tl{ \tl_gset:Nx\g_ocgxii_lnkcol_tl{{\l_tmpa_tl}} \ocgxii_colourlink_end: } } %check whether end-of-page ocg stack has settled \iow_shipout:Nx\@mainaux{ \token_to_str:N\ocgxii@newkey{ocgx2.oldstack.\int_use:N\g_ocgxii_page_int}{ \seq_use:cn{g_pending_ocgs_on_\int_use:c{g_ocgxii_page_int}_seq}{,} } } \bool_if:nT{ !\cs_if_exist:cTF{ocgx2.oldstack.\int_use:N\g_ocgxii_page_int}{ \str_if_eq_x_p:nn{ \tl_use:c{ocgx2.oldstack.\int_use:N\g_ocgxii_page_int} }{ \seq_use:cn{g_pending_ocgs_on_\int_use:c{g_ocgxii_page_int}_seq}{,} } }{ \c_false_bool } }{ \tl_if_exist:NF\g_ocgxii_rerunwarned_tl{ \tl_new:N\g_ocgxii_rerunwarned_tl \AtEndDocument{\msg_warning:nn{ocgx2}{rerun}} } } %now close pending ocgs \seq_map_variable:cNn{ g_pending_ocgs_on_\int_use:c{g_ocgxii_page_int}_seq }\l_tmpb_tl{\ocgbase_oc_emc:} } %begin-of-page action \pbs_bop_action:n{ % re-open all pending ocgs in original order \seq_set_eq:Nc\l_ocgxii_pending_ocgs_seq{ g_pending_ocgs_on_\int_use:c{g_ocgxii_page_int}_seq } \seq_reverse:N\l_ocgxii_pending_ocgs_seq \seq_map_variable:NNn\l_ocgxii_pending_ocgs_seq\l_tmpa_tl{ \ocgbase_oc_bdc:n{\l_tmpa_tl} } % re-open the colourlink opened last \seq_get:cNT{g_pending_lnkcols_on_\int_use:c{g_ocgxii_page_int}_seq}\l_tmpa_tl{ \tl_gset:Nx\g_ocgxii_lnkcol_tl{{\l_tmpa_tl}} \ocgxii_colourlink_begin: } \int_gincr:N\g_ocgxii_page_int % copy pending ocg stack from previous page, if it has not been initialized % yet from aux file \seq_if_exist:cF{g_pending_ocgs_on_\int_use:c{g_ocgxii_page_int}_seq}{ \seq_gset_eq:cc{ g_pending_ocgs_on_\int_use:c{g_ocgxii_page_int}_seq }{ g_pending_ocgs_on_\int_eval:n{\g_ocgxii_page_int-\c_one}_seq } } %the same for link colour stack \seq_if_exist:cF{g_pending_lnkcols_on_\int_use:c{g_ocgxii_page_int}_seq}{ \seq_gset_eq:cc{ g_pending_lnkcols_on_\int_use:c{g_ocgxii_page_int}_seq }{ g_pending_lnkcols_on_\int_eval:n{\g_ocgxii_page_int-\c_one}_seq } } } \int_new:N\g_ocgxii_page_int %abs. page counter \cs_new_nopar:Nn\ocgxii_ocglist_reset:{ \tl_clear_new:N\l_ocgxii_u_list_tl \tl_clear_new:N\l_ocgxii_d_list_tl \tl_clear_new:N\l_ocgxii_e_list_tl \tl_clear_new:N\l_ocgxii_x_list_tl } \cs_new_nopar:Nn\ocgxii_ocglist_build:Nn{ \tl_set:Nx\l_ocglistarg_tl{#2}\tl_trim_spaces:N\l_ocglistarg_tl \seq_set_split:NnV\l_ocgxii_ocglistarg_seq{~}\l_ocglistarg_tl \seq_map_variable:NNn\l_ocgxii_ocglistarg_seq\l_tempa_tl{ \ocgxii_process_ocgref:NN#1\l_tempa_tl } } \cs_new:Nn\ocgxii_commalist_process:n{ \seq_set_split:Nnn\l_tmpa_seq{,}{#1} \ocgxii_ocglist_build:Nn\l_ocgxii_e_list_tl{\seq_item:Nn\l_tmpa_seq{1}} \ocgxii_ocglist_build:Nn\l_ocgxii_x_list_tl{\seq_item:Nn\l_tmpa_seq{2}} \ocgxii_ocglist_build:Nn\l_ocgxii_d_list_tl{\seq_item:Nn\l_tmpa_seq{3}} \ocgxii_ocglist_build:Nn\l_ocgxii_u_list_tl{\seq_item:Nn\l_tmpa_seq{4}} } \cs_new_nopar:Nn\ocgxii_ocglist_process_idlist:nn{ \ocgxii_ocglist_reset: \tl_set:Nx\l_ocgxii_opt_tl{#1}\tl_remove_all:Nn\l_ocgxii_opt_tl{~} \str_case_x:nnF{\l_ocgxii_opt_tl}{ {triggerocg=onmouseup}{ \ocgxii_ocglist_build:Nn\l_ocgxii_u_list_tl{#2} } {triggerocg=onmousedown}{ \ocgxii_ocglist_build:Nn\l_ocgxii_d_list_tl{#2} } {triggerocg=onmouseenter}{ \ocgxii_ocglist_build:Nn\l_ocgxii_e_list_tl{#2} } {triggerocg=onmouseexit}{ \ocgxii_ocglist_build:Nn\l_ocgxii_x_list_tl{#2} } {triggerocg=allactions}{ \ocgxii_commalist_process:n{#2} } }{ \msg_error:nnx{ocgx2}{unknown~option}{\l_ocgxii_opt_tl} } } \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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \DeclareDocumentCommand\switchocg{s o m +m}{ \ocgxii_actionsocg:nnnnnn{#1}{#2}{#3}{}{}{#4} } \DeclareDocumentCommand\showocg{s o m +m}{ \ocgxii_actionsocg:nnnnnn{#1}{#2}{}{#3}{}{#4} } \DeclareDocumentCommand\hideocg{s o m +m}{ \ocgxii_actionsocg:nnnnnn{#1}{#2}{}{}{#3}{#4} } \DeclareDocumentCommand\actionsocg{s o m m m +m}{ \ocgxii_actionsocg:nnnnnn{#1}{#2}{#3}{#4}{#5}{#6} } \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 \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<> \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 <> } \str_if_eq_x:nnF{}{ \l_ocgxii_toswitch_d_tl\l_ocgxii_toshow_d_tl\l_ocgxii_tohide_d_tl }{ /D <> } \str_if_eq_x:nnF{}{ \l_ocgxii_toswitch_e_tl\l_ocgxii_toshow_e_tl\l_ocgxii_tohide_e_tl }{ /E <> } \str_if_eq_x:nnF{}{ \l_ocgxii_toswitch_x_tl\l_ocgxii_toshow_x_tl\l_ocgxii_tohide_x_tl }{ /X <> } >> }\box_use_clear:N\l_tmpa_box \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 \pbs_pdflink:nn{ /Subtype/Link /A <> %look and feel of hyperref links, if hyperref has been loaded \cs_if_exist:NTF\Hy@setpdfborder{ \Hy@setpdfborder\g_ocgxii_patch_tl \ifx\@pdfhighlight\@empty\else/H\@pdfhighlight\fi \ifx\@linkbordercolor\relax\else/C[\@linkbordercolor]\fi \ifHy@pdfa /F~4\fi }{ /Border~[0~0~0] } }{ \cs_if_exist:NTF\Hy@colorlink{ \Hy@colorlink\@linkcolor#6\Hy@endcolorlink\Hy@VerboseLinkStop }{#6} } } } %mimic commands from ocg-p \cs_new:Npn\toggleocgs{\switchocg*} \cs_new:Npn\showocgs{\showocg*} \cs_new:Npn\hideocgs{\hideocg*} \cs_new:Npn\setocgs{\actionsocg*} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cs_new:Nn\ocgxii_process_ocgref:NN{ \str_if_eq_x:nnF{#2}{}{ \tl_if_exist:cTF{ocgx2.ocg.#2}{ \tl_put_right:Nx#1{~\tl_use:c{ocgx2.ocg.#2}} }{ \msg_warning:nnx{ocgx2}{undefined~OCG}{#2} \tl_if_exist:NF\g_ocgxii_refundefwarned_tl{ \tl_new:N\g_ocgxii_refundefwarned_tl \AtEndDocument{\msg_warning:nn{ocgx2}{undefined~OCGs}} } } } } %command opts \keys_define:nn{ocgx2/user}{ viewocg .choice:, viewocg / always .code:n={ \tl_set:Nn\l_ocgxii_view_tl{/View<>}}, viewocg / never .code:n={ \tl_set:Nn\l_ocgxii_view_tl{/View<>}}, viewocg / ifvisible .code:n={ \tl_clear:N\l_ocgxii_view_tl}, viewocg .default:n={ifvisible}, printocg .choice:, printocg / always .code:n={ \tl_set:Nn\l_ocgxii_print_tl{/Print<>}}, printocg / never .code:n={ \tl_set:Nn\l_ocgxii_print_tl{/Print<>}}, printocg / ifvisible .code:n={ \tl_clear:N\l_ocgxii_print_tl}, printocg .default:n={ifvisible}, exportocg .choice:, exportocg / always .code:n={ \tl_set:Nn\l_ocgxii_export_tl{/Export<>}}, exportocg / never .code:n={ \tl_set:Nn\l_ocgxii_export_tl{/Export<>}}, 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}} }, listintoolbar .default:n={iffirstuse}, showingui .meta:n = {listintoolbar=#1}, showingui .default:n={iffirstuse}, radiobtngrp .code:n = { \seq_put_right:Nx\l_ocgxii_rbgrps_seq{#1} }, radiobtngrp .value_required:n = {true} } \cs_new:Nn\ocgxii_reset_cmd_opts:{ \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 %stack of radio button group names the current ocg belongs to \seq_clear_new:N\l_ocgxii_rbgrps_seq } \msg_set:nnn{ocgx2}{rerun}{Rerun~to~get~OCG~references~right!} \msg_set:nnn{ocgx2}{undefined~OCG}{ Line~\msg_line_number: :~OCG~`#1'~is~not~defined. } \msg_set:nnn{ocgx2}{undefined~OCGs}{There~were~undefined~OCGs!} \msg_set:nnn{ocgx2}{unknown~option}{ Line~\msg_line_number: :~unknown~option~`#1'. } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % patch hyperref to ensure compatibility with our `ocgcolorlinks' option % % Plus: % % * add `ocgcolorlinks' support to all drivers % % * allows for `ocgcolorlinks' extending over % % line-breaks AND page-breaks % % with pdftex, luatex, xetex, dvipdfmx drivers % % based on Ben Lerner's solution % http://tex.stackexchange.com/a/104227; % with some improvements %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \sys_if_output_pdf:TF{ \cs_new:Nn\ocgxii_literal_page:n{\pdfliteral~page~{#1}} }{ \bool_if:NT\g_ocgxii_dvipdfmx_bool{ %dvipdfmx/XeTeX \cs_new:Nn\ocgxii_literal_page:n{\special{pdf:code~#1}} } } \cs_new_nopar:Nn\ocgxii_colourlink_begin:{} \cs_new_nopar:Nn\ocgxii_colourlink_end:{} \cs_new_nopar:Nn\ocgxii_colourlink_nobreak_begin:{ \hbox_set:Nw\l_tmpa_box\color@begingroup \tl_set_eq:NN\color@setgroup\group_begin: } \cs_new_nopar:Nn\ocgxii_colourlink_nobreak_end:{ \color@endgroup\hbox_set_end: \mbox{ \ocgbase_oc_bdc:n{\ocgxii@OCPrint} \hbox_to_zero:n{\box_use:N\l_tmpa_box\hss} \ocgbase_oc_emc: \ocgbase_oc_bdc:n{\ocgxii@OCView} \group_begin: \exp_after:wN\HyColor@UseColor\l_ocgxii_lnkcol_tl \box_use_clear:N\l_tmpa_box \group_end: \ocgbase_oc_emc: } } \seq_new:N\g_ocgxii_lnk_color_seq %stack of colours of currently open links \tl_new:N\g_ocgxii_patch_tl % `BorderArrayPatch' for dvips \bool_if:nTF{\sys_if_output_dvi_p: && !\g_ocgxii_dvipdfmx_bool}{ % non-breakable links in dvips \cs_new_nopar:Nn\ocgxii_enable_ocglinks:{ \def\Hy@colorlink##1{ \group_begin: \tl_set:Nn\l_ocgxii_lnkcol_tl{##1} \ocgxii_colourlink_nobreak_begin: } \def\Hy@endcolorlink{ \ocgxii_colourlink_nobreak_end: \group_end: } } \tl_gset:Nn\g_ocgxii_patch_tl{BorderArrayPatch} }{ % pdftex,luatex,xetex,dvipdfmx: % ocgcolorlinks that extend over line and page breaks \cs_new_nopar:Nn\ocgxii_enable_ocglinks:{ \def\Hy@colorlink##1{ \ifx\Hy@setbreaklinks\@gobble\else \Hy@breaklinkstrue \fi \ifHy@breaklinks \seq_get_left:NNT\g_ocgxii_lnk_color_seq\l_tmpa_tl{ \tl_gset_eq:NN\g_ocgxii_lnkcol_tl\l_tmpa_tl \ocgxii_colourlink_end: } \group_begin: \ocgxii_colourlink_begin: \seq_gpush:Nx\g_ocgxii_lnk_color_seq{{##1}} \ocgxii_stack_shipout:NN\ocgxii@lnkcol@stack@on@page\g_ocgxii_lnk_color_seq \else \group_begin: \tl_set:Nn\l_ocgxii_lnkcol_tl{##1} \ocgxii_colourlink_nobreak_begin: \fi } \def\Hy@endcolorlink{ \ifHy@breaklinks \seq_gpop:NN\g_ocgxii_lnk_color_seq\l_tmpa_tl \tl_gset_eq:NN\g_ocgxii_lnkcol_tl\l_tmpa_tl \ocgxii_stack_shipout:NN\ocgxii@lnkcol@stack@on@page\g_ocgxii_lnk_color_seq \ocgxii_colourlink_end: \group_end: \seq_get_left:NNT\g_ocgxii_lnk_color_seq\l_tmpa_tl{ \tl_gset_eq:NN\g_ocgxii_lnkcol_tl\l_tmpa_tl \ocgxii_colourlink_begin: } \else \ocgxii_colourlink_nobreak_end: \group_end: \fi } } \cs_gset_nopar:Nn\ocgxii_colourlink_begin:{ \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} } \ocgbase_oc_bdc:n{\ocgxii@OCPrint} \ocgxii_literal_page:n{-88888~-88888~99999~99999~re~f} \ocgbase_oc_emc: \ocgbase_oc_bdc:n{\ocgxii@OCView} \group_begin: \exp_after:wN\HyColor@UseColor\g_ocgxii_lnkcol_tl \ocgxii_literal_page:n{-88888~-88888~99999~99999~re~f} \group_end: \ocgbase_oc_emc: \ocgxii_literal_page:n{0~Tr~Q} } } % user command for protecting graphical content (external file, inline % [e. g. TikZ], \fbox{...}) inside breakable ocgcolorlink \DeclareDocumentCommand\ocglinkprotect{m}{ \seq_get_left:NNT\g_ocgxii_lnk_color_seq\l_tmpa_tl{ \tl_gset_eq:NN\g_ocgxii_lnkcol_tl\l_tmpa_tl \ocgxii_colourlink_end: \group_begin: \tl_set_eq:NN\l_ocgxii_lnkcol_tl\l_tmpa_tl \ocgxii_colourlink_nobreak_begin: } #1 \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 \vss \hbox_to_zero:n{\skip_horizontal:n{2\paperwidth}.\hss} \skip_vertical:n{2\paperheight} } \ocgxii_colourlink_begin: } } \bool_if:NT\l_ocgxii_ocgcolorlinks_bool{ \@ifpackageloaded{hyperref}{ \Hy@colorlinkstrue \AtBeginDocument{ \ocgbase_new_ocg:nnn{OCView}{/Print<>}{on} \tl_gset:Nx\ocgxii@OCView{\ocgbase_last_ocg:} \tl_gset:cx{ocgxii@OCView.opts}{showingui=never,printocg=never} \ocgbase_new_ocg:nnn{OCPrint}{/Print<>}{off} \tl_gset:Nx\ocgxii@OCPrint{\ocgbase_last_ocg:} \tl_gset:cx{ocgxii@OCPrint.opts}{showingui=never,printocg=always} \ocgxii_enable_ocglinks: \iow_now:Nx\@mainaux{ \token_to_str:N\ocgxii@newkey{ocgx2.ocg.OCView}{\ocgxii@OCView} } \iow_now:Nx\@mainaux{ \token_to_str:N\ocgxii@newkey{ocgx2.ocg.OCPrint}{\ocgxii@OCPrint} } } }{ \msg_error:nnn{ocgx2}{missing~package}{hyperref} } } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % TikZ related code follows (to be enabled with package option `tikz') \bool_if:NF\l_ocgxii_tikz_bool{\endinput} \ExplSyntaxOff \RequirePackage{tikz} \usetikzlibrary{calc} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Copyright notice: The code that follows until the end of the file was % taken from Paul Gaborit's `tikzlibraryocgx.code.tex' with minor additions. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \tikzset{ ocg/.style={ocg/.cd,#1,/tikz/.cd}, ocg={ % parameters name/.store in=\ocgxii@name, opts/.store in=\ocgxii@opts, visibility/.store in=\ocgxii@visibility, status/.is choice, status/visible/.style={visibility=1}, status/invisible/.style={visibility=0}, status/true/.style={visibility=1}, status/false/.style={visibility=0}, status/on/.style={visibility=1}, status/off/.style={visibility=0}, status/1/.style={visibility=1}, status/0/.style={visibility=0}, % default values name=, opts=, status=on, % ref ref/.style={ /tikz/execute at begin scope={% \begin{ocg}[\ocgxii@opts]{% \ifx\empty\ocgxii@name\empty#1\else\ocgxii@name\fi% }{#1}{\ocgxii@visibility}}, /tikz/execute at end scope={\end{ocg}}, }, }, switch ocg/.style={ postaction={ path picture={ \path let \p1 = (path picture bounding box.south west), \p2 = (path picture bounding box.north east), \p3 = (\x2-\x1,\y2-\y1) in (path picture bounding box.center) node[inner sep=0pt,anchor=center,outer sep=0pt] {\switchocg*{#1}{\phantom{\rule{\x3}{\y3}}}}; } }, }, switch ocg with mark on/.style 2 args={ postaction={ path picture={ \begin{ocg}{#1}{#1}{1} \draw (path picture bounding box.south west) -- (path picture bounding box.north east) (path picture bounding box.south east) -- (path picture bounding box.north west) ; \end{ocg} }, switch ocg={#1 #2}, } }, switch ocg with mark off/.style 2 args={ postaction={ path picture={ \begin{ocg}{#1}{#1}{0} \draw (path picture bounding box.south west) -- (path picture bounding box.north east) (path picture bounding box.south east) -- (path picture bounding box.north west) ; \end{ocg} }, switch ocg={#1 #2}, } }, show ocg/.style={ postaction={ path picture={ \path let \p1 = (path picture bounding box.south west), \p2 = (path picture bounding box.north east), \p3 = (\x2-\x1,\y2-\y1) in (path picture bounding box.center) node[inner sep=0pt,anchor=center] {\showocg*{#1}{\phantom{\rule{\x3}{\y3}}}}; }, }, }, hide ocg/.style={ postaction={ path picture={ \path let \p1 = (path picture bounding box.south west), \p2 = (path picture bounding box.north east), \p3 = (\x2-\x1,\y2-\y1) in (path picture bounding box.center) node[inner sep=0pt,anchor=center] {\hideocg*{#1}{\phantom{\rule{\x3}{\y3}}}}; }, }, }, actions ocg/.style n args={3}{ postaction={ path picture={ \path let \p1 = (path picture bounding box.south west), \p2 = (path picture bounding box.north east), \p3 = (\x2-\x1,\y2-\y1) in (path picture bounding box.center) node[inner sep=0pt,anchor=center] {\actionsocg*{#1}{#2}{#3}{\phantom{\rule{\x3}{\y3}}}}; }, }, }, }