From 2e6d28e9233f26ef14c649d8189e6d17393a1824 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 4 Jul 2019 21:13:54 +0000 Subject: ocgx2 (4jul19) git-svn-id: svn://tug.org/texlive/trunk@51552 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/latex/ocgx2/ChangeLog | 7 + Master/texmf-dist/doc/latex/ocgx2/README.txt | 4 +- Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty | 13 +- Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty | 368 ++++++++++++++++---------- 4 files changed, 242 insertions(+), 150 deletions(-) (limited to 'Master/texmf-dist') diff --git a/Master/texmf-dist/doc/latex/ocgx2/ChangeLog b/Master/texmf-dist/doc/latex/ocgx2/ChangeLog index 396585d5147..94f24020575 100644 --- a/Master/texmf-dist/doc/latex/ocgx2/ChangeLog +++ b/Master/texmf-dist/doc/latex/ocgx2/ChangeLog @@ -1,3 +1,10 @@ +2019-07-04 + * v0.43: ocgx2.sty + * v0.16: ocgbase.sty + * fix: ocmd-related refactoring; now, \ocgbase@insert@oc takes into account + open OCMD layers; + * new: OCMD visibility expressions also accept references to other ocmd + 2019-05-28 * v0.42: ocgx2.sty * new: `ocmd' TikZ style added; option `radiobtngrp' renamed to diff --git a/Master/texmf-dist/doc/latex/ocgx2/README.txt b/Master/texmf-dist/doc/latex/ocgx2/README.txt index 93aa14723f2..903955efacd 100644 --- a/Master/texmf-dist/doc/latex/ocgx2/README.txt +++ b/Master/texmf-dist/doc/latex/ocgx2/README.txt @@ -136,10 +136,10 @@ functions \Or{, , ...} \Not{} -In the argument list, items represent OCG ids and nested Boolean +In the argument list, items represent OCG/OCMD ids as well as nested Boolean functions. As nesting of the three functions is possible, any thinkable visibility relationship can be defined. Note that `\Not{...}' accepts only one -item, either an OCG id or a nested function. Also note that Boolean functions +item, either an OCG/OCMD id or a nested function. Also note that Boolean functions and policy directives cannot be intermixed. As a trivial example, the visibility expression equivalent of the policy diff --git a/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty b/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty index d30786435dd..fd1abcfc3a4 100644 --- a/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty +++ b/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty @@ -103,8 +103,8 @@ \RequirePackage{pdfbase} \RequirePackage{expl3} -\def\g@ocgbase@date@tl{2019/05/24} -\def\g@ocgbase@version@tl{0.15} +\def\g@ocgbase@date@tl{2019/07/04} +\def\g@ocgbase@version@tl{0.16} \ProvidesExplPackage{ocgbase}{\g@ocgbase@date@tl}{\g@ocgbase@version@tl} {support package for ocgx2.sty} @@ -337,14 +337,6 @@ \cs_new_protected_nopar:Nn\ocgbase_open_stack_pop:N{ \seq_gpop:NN\g_ocgbase_open_stack_seq#1} -%command that inserts /OC <> entry; -%for use within annotation/xobject dicts -\cs_new_nopar:Nn\ocgbase_insert_oc:{ - \seq_if_empty:NF\g_ocgbase_open_stack_seq{ - /OC~<> - } -} - %l2e versions \cs_gset_eq:NN\ocgbase@new@ocg\ocgbase_new_ocg:nnn \cs_gset_eq:NN\ocgbase@last@ocg\ocgbase_last_ocg: @@ -355,6 +347,5 @@ \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@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 c3b27b12b20..dd46efcfe53 100644 --- a/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty +++ b/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty @@ -48,19 +48,23 @@ \RequirePackage{xparse} \RequirePackage{l3keys2e} -\def\g@ocgxii@date@tl{2019/05/28} -\def\g@ocgxii@version@tl{0.42} +\def\g@ocgxii@date@tl{2019/07/04} +\def\g@ocgxii@version@tl{0.43} \ProvidesExplPackage{ocgx2}{\g@ocgxii@date@tl}{\g@ocgxii@version@tl} {ports `ocgx' functionality to dvips+ps2pdf, xelatex and dvipdfmx} %creating global definitions \cs_new_protected:Npn\ocgxii@newkey#1#2{\tl_gset:cx{#1}{#2}} +\cs_new_protected:Npn\ocgxii@newkeynoexp#1#2{\tl_gset:cn{#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@newkeynoexp[2]{} + } \iow_now:Nx\@mainaux{ \token_to_str:N\providecommand\token_to_str:N\ocgxii@ocg@stack@on@page[2]{} } @@ -201,6 +205,8 @@ \l_ocgxii_view_tl\l_ocgxii_print_tl\l_ocgxii_export_tl }{\l_ocgxii_argiv_tl} \tl_gset:cx{ocgxii_ocg_#3}{\ocgbase_last_ocg:} + \tl_gset:cx{ocgx2.ocg.\ocgbase_last_ocg:}{\ocgbase_last_ocg:} + \tl_gset:cx{ocgx2.ocg.#3}{\ocgbase_last_ocg:} \iow_now:Nx\@mainaux{ \token_to_str:N\ocgxii@newkey{ocgx2.ocg.#3}{\ocgbase_last_ocg:} } @@ -217,11 +223,11 @@ \AtEndDocument{\msg_warning:nn{ocgx2}{rerun}} } } - \tl_gset:cx{ocgx2.ocg.#3}{\tl_use:c{ocgxii_ocg_#3}} \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_ocg_#3}} } \ocgbase_open_stack_push:n{\tl_use:c{ocgxii_ocg_#3}} + \ocgxii_make_oc_entry: \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{ @@ -237,190 +243,266 @@ \ocgbase_oc_emc: \ocgbase_tree_node_end: \ocgbase_open_stack_pop:N\l_trash_tl + \ocgxii_make_oc_entry: \ocgxii_stack_shipout:NN\ocgxii@ocg@stack@on@page\g_ocgbase_open_stack_seq } % OCMD implementation \DeclareDocumentEnvironment{ocmd}{O{}m}{ - \ocgxii_begin_ocmd:nn{#1}{#2} + \ocgxii_begin_ocmd:on{#1}{#2} + \ignorespaces }{ + \unskip \ocgxii_end_ocmd: } \cs_new_protected_nopar:Nn\ocgxii_begin_ocmd:nn{ % #1: id, - \group_begin: % #2: visib. expression or policy - \bool_if:nF{ %do nothing if we re-open existing ocmd - \tl_if_blank:oTF{#1}{ - \c_false_bool - }{ - \tl_if_exist_p:c{ocgxii_ocmd_#1} - } - }{ %new ocmd - \ocgxii_read_ocmd_visbility:nN{#2}\l_ocgxii_ocmd_visibility_tl - \pbs_pdfobj:nnn{}{dict}{ - /Type/OCMD\l_ocgxii_ocmd_visibility_tl - } + \bool_if:nTF{ % #2: visib. expr. or policy + \tl_if_blank:oTF{#1}{ + \c_false_bool + }{ + \tl_if_exist_p:c{ocgxii_ocmd_#1} + } + }{ + % re-open existing ocmd + \tl_set_eq:Nc\l_ocgxii_cur_ocmd_tl{ocgxii_ocmd_#1} + }{ + % new ocmd + \group_begin: + \ocgxii_ocmd_read_visbility:nN{#2}\l_ocgxii_ocmd_visibility_tl + \pbs_pdfobj:nnn{}{dict}{/Type/OCMD\l_ocgxii_ocmd_visibility_tl} + %if only visb. policy is given, generate equivalent visib. expression, + %needed for stack of open layers and \ocgxii_make_oc_entry: command + \ocgxii_ocmd_make_equiv_ve:nN{#2}\l_ocgxii_ocmd_equiv_ve_tl + \tl_gset:co{ocgx2.ocmd.\pbs_pdflastobj:}{\l_ocgxii_ocmd_equiv_ve_tl} + \group_end: + \tl_set:Nx\l_ocgxii_cur_ocmd_tl{\pbs_pdflastobj:} + \tl_if_blank:oF{#1}{ \tl_gset:cx{ocgxii_ocmd_#1}{\pbs_pdflastobj:} + \iow_now:Nn\@mainaux{\ocgxii@newkeynoexp{ocgx2.ocmd.#1}{#2}} } - \ocgbase_open_stack_push:n{\tl_use:c{ocgxii_ocmd_#1}} - \ocgxii_stack_shipout:NN\ocgxii@ocg@stack@on@page\g_ocgbase_open_stack_seq - \group_end: - \ocgbase_oc_bdc:n{\tl_use:c{ocgxii_ocmd_#1}} - \ignorespaces + } + \ocgbase_open_stack_push:n{\l_ocgxii_cur_ocmd_tl} + \ocgxii_make_oc_entry: + \ocgxii_stack_shipout:NN\ocgxii@ocg@stack@on@page\g_ocgbase_open_stack_seq + \ocgbase_oc_bdc:n{\l_ocgxii_cur_ocmd_tl} } +\cs_generate_variant:Nn\ocgxii_begin_ocmd:nn{on} \cs_new_protected_nopar:Nn\ocgxii_end_ocmd:{ - \unskip \ocgbase_oc_emc: \ocgbase_open_stack_pop:N\l_trash_tl + \ocgxii_make_oc_entry: %update \ocgxii_stack_shipout:NN\ocgxii@ocg@stack@on@page\g_ocgbase_open_stack_seq } %visibility expressions -\cs_new_protected_nopar:Nn\ocgxii_read_ocmd_visbility:nN{ +\cs_new_protected_nopar:Nn\ocgxii_ocmd_read_visbility:nN{ \int_zero:N\l_ocgxii_ve_cnt_int \int_zero:N\l_ocgxii_vp_cnt_int \tl_clear_new:N#2 - \clist_map_inline:nn{#1}{\ocgxii_omcd_visib_map_func:nN{##1}#2} + \clist_map_inline:nn{#1}{\ocgxii_omcd_parse_argument:nN{##1}#2} } -\cs_new_protected_nopar:Nn\ocgxii_omcd_visib_map_func:nN{ - \cs_set_eq:NN\Not\ocgxii_ve_check:n - \cs_set_eq:NN\And\ocgxii_ve_check:n - \cs_set_eq:NN\Or \ocgxii_ve_check:n +\cs_new_protected_nopar:Nn\ocgxii_omcd_parse_argument:nN{ \cs_set_eq:NN\AllOn \ocgxii_vp_check:n \cs_set_eq:NN\AnyOn \ocgxii_vp_check:n \cs_set_eq:NN\AnyOff\ocgxii_vp_check:n \cs_set_eq:NN\AllOff\ocgxii_vp_check:n + \cs_set_eq:NN\Not\ocgxii_ve_check:n + \cs_set_eq:NN\And\ocgxii_ve_check:n + \cs_set_eq:NN\Or \ocgxii_ve_check:n \tl_if_exist:cTF{ocgx2.ocg.#1}{ \msg_error:nnxx{ocgx2}{generic~msg}{ OCG~ids~cannot~be~directly~used~in~the~visibility~argument~of~an~ `ocmd'~environment. }{\g_ocgxii_help_msg_tl} }{ - \tl_if_exist:cTF{ocgxii_#1}{ - \str_case_e:nn{\tl_use:c{ocgxii_#1}}{ - {VisExpr}{ - \int_incr:N\l_ocgxii_ve_cnt_int - \int_compare:nNnTF{\l_ocgxii_ve_cnt_int}>{1}{ - \msg_error:nnnn{ocgx2}{generic~msg}{ - More~than~one~visibility~expression~passed~to~the~`ocmd'~ - environment. + \tl_if_exist:cTF{ocgx2.ocmd.#1}{ + \msg_error:nnxx{ocgx2}{generic~msg}{ + OCMD~ids~cannot~be~directly~used~in~the~visibility~argument~of~an~ + `ocmd'~environment. + }{\g_ocgxii_help_msg_tl} + }{ + \tl_if_exist:cTF{ocgxii_#1}{ + \str_case_e:nn{\tl_use:c{ocgxii_#1}}{ + {VisExpr}{ + \int_incr:N\l_ocgxii_ve_cnt_int + \int_compare:nNnTF{\l_ocgxii_ve_cnt_int}>{1}{ + \msg_error:nnnn{ocgx2}{generic~msg}{ + More~than~one~visibility~expression~passed~to~the~`ocmd'~ + environment. + }{ + At~most~one~visibility~expression~is~allowed.~A~visibility~ + expression~is~a~boolean~expression~built~by~nesting~any~number~of~ + \And{...},~\Or{...},~\Not{...}~commands. + } }{ - At~most~one~visibility~expression~is~allowed.~A~visibility~ - expression~is~a~boolean~expression~built~by~nesting~any~number~of~ - \And{...},~\Or{...},~\Not{...}~commands. + \tl_put_right:Nx#2{/VE~} + \ocgxii_ocmd_expression_parser:nN{#1}#2 } - }{ - \ocgxii_ve_start:nN{#1}#2 } - } - {VisPol}{ - \int_incr:N\l_ocgxii_vp_cnt_int - \int_compare:nNnTF{\l_ocgxii_vp_cnt_int}>{1}{ - \msg_error:nnnn{ocgx2}{generic~msg}{ - More~than~one~visibility~policy~passed~to~the~`ocmd'~environment. + {VisPol}{ + \int_incr:N\l_ocgxii_vp_cnt_int + \int_compare:nNnTF{\l_ocgxii_vp_cnt_int}>{1}{ + \msg_error:nnnn{ocgx2}{generic~msg}{ + More~than~one~visibility~policy~passed~to~the~`ocmd'~environment. + }{ + At~most~one~visibility~policy~out~of~\AllOn{...},~\AnyOn{...},~ + \AnyOff{...},~\AllOff{...}~is~allowed.~Any~number~of~OCG~IDs,~ + separated~by~commas,~may~be~passed~as~arguments~to~these~ + commands,~but~commands~may~not~be~nested.~For~complex~visibilty~ + relations,~consider~using~a~visibility~expression. + } }{ - At~most~one~visibility~policy~out~of~\AllOn{...},~\AnyOn{...},~ - \AnyOff{...},~\AllOff{...}~is~allowed.~Any~number~of~OCG~IDs,~ - separated~by~commas,~may~be~passed~as~arguments~to~these~ - commands,~but~commands~may~not~be~nested.~For~complex~visibilty~ - relations,~consider~using~a~visibility~expression. + \ocgxii_ocmd_expression_parser:nN{#1}#2 } - }{ - \ocgxii_vp_start:nN{#1}#2 } } + }{ + \msg_error:nnxx{ocgx2}{generic~msg}{ + The~visibility~argument~of~the~`ocmd'~environment~cannot~be~parsed. + }{\g_ocgxii_help_msg_tl} } - }{ - \msg_error:nnxx{ocgx2}{generic~msg}{ - The~visibility~argument~of~the~`ocmd'~environment~cannot~be~parsed. - }{\g_ocgxii_help_msg_tl} } } } -\tl_set:Nn\g_ocgxii_help_msg_tl{ - At~most~one~visibility~policy~and,~separated~by~a~comma,~at~most~one~ - visibility~expression~may~be~passed~to~the~visibility~argument.~A~visibility~ - policy~is~defined~by~one~of~\AllOn{...},~\AnyOn{...},~\AnyOff{...},~ - \AllOff{...}.~A~visibility~expression~is~a~boolean~expression~built~by~ - nesting~any~number~of~\And{...},~\Or{...},~\Not{...}~commands.~If~both~are~ - provided,~the~visibility~expression~takes~precedence~over~the~policy,~but~the~ - latter~may~be~used~as~fallback~by~non-conforming~PDF~viewers. -} -\int_new:N\l_ocgxii_vp_cnt_int %number of visib. policies -\int_new:N\l_ocgxii_ve_cnt_int %number of visib. expressions -\cs_new_protected_nopar:Nn\ocgxii_vp_start:nN{ - \cs_set_eq:NN\AllOn \ocgxii_vp_allon:nN - \cs_set_eq:NN\AnyOn \ocgxii_vp_anyon:nN - \cs_set_eq:NN\AnyOff\ocgxii_vp_anyoff:nN - \cs_set_eq:NN\AllOff\ocgxii_vp_alloff:nN - #1#2 +\cs_generate_variant:Nn\ocgxii_omcd_parse_argument:nN{xN} +\cs_generate_variant:Nn\ocgxii_omcd_parse_argument:nN{oN} +\cs_new_protected_nopar:Nn\ocgxii_ocmd_expression_parser:nN{ + \cs_set_eq:NN\AllOn \ocgxii_vp_check:n + \cs_set_eq:NN\AnyOn \ocgxii_vp_check:n + \cs_set_eq:NN\AnyOff\ocgxii_vp_check:n + \cs_set_eq:NN\AllOff\ocgxii_vp_check:n + \cs_set_eq:NN\Not\ocgxii_ve_check:n + \cs_set_eq:NN\And\ocgxii_ve_check:n + \cs_set_eq:NN\Or \ocgxii_ve_check:n + \tl_if_exist:cTF{ocgx2.ocg.#1}{% ocg reference + \tl_put_right:Nx#2{~\tl_use:c{ocgx2.ocg.#1}} + }{ + \tl_if_exist:cTF{ocgx2.ocmd.#1}{% ocmd reference + \ocgxii_ocmd_expression_parser:vN{ocgx2.ocmd.#1}#2 + }{ + \tl_if_exist:cTF{ocgxii_#1}{% visib. bool expression or policy directive + \bool_if:nTF{ + \str_if_eq_p:ee{\tl_use:c{ocgxii_#1}}{VisExpr} && + \bool_if_p:N\l_ocgxii_vp_open_bool || + \str_if_eq_p:ee{\tl_use:c{ocgxii_#1}}{VisPol} && + \bool_if_p:N\l_ocgxii_ve_open_bool + }{ + \msg_error:nnxx{ocgx2}{generic~msg}{ + Visibility~policy~and~expression~commands~cannot~be~mixed. + }{\g_ocgxii_help_msg_tl} + }{ + \bool_if:nT{ + \str_if_eq_p:ee{\tl_use:c{ocgxii_#1}}{VisPol} && + \bool_if_p:N\l_ocgxii_vp_open_bool + }{ + \msg_error:nnxx{ocgx2}{generic~msg}{ + Visibility~policy~commands~cannot~be~nested.~For~more~complex~ + visibilty~relations,~consider~using~a~visibility~expression. + }{\g_ocgxii_help_msg_tl} + } + } + \cs_set_eq:NN\AllOn \ocgxii_vp_allon:nN + \cs_set_eq:NN\AnyOn \ocgxii_vp_anyon:nN + \cs_set_eq:NN\AnyOff\ocgxii_vp_anyoff:nN + \cs_set_eq:NN\AllOff\ocgxii_vp_alloff:nN + \cs_set_eq:NN\Not\ocgxii_ve_not:nN + \cs_set_eq:NN\And\ocgxii_ve_and:nN + \cs_set_eq:NN\Or \ocgxii_ve_or:nN + #1#2 + }{ + \msg_warning:nnx{ocgx2}{undefined~OCG}{#1} + \tl_if_exist:NF\g_ocgxii_refundefwarned_tl{ + \tl_new:N\g_ocgxii_refundefwarned_tl + \AtEndDocument{\msg_warning:nn{ocgx2}{undefined~OCGs}} + } + } + } + } } +\cs_generate_variant:Nn\ocgxii_ocmd_expression_parser:nN{vN} +% visib. policy directives \cs_new_protected_nopar:Nn\ocgxii_vp_allon:nN{ + \bool_set_true:N\l_ocgxii_vp_open_bool \tl_put_right:Nx#2{/P/AllOn/OCGs~\g_ocgxii_left_bracket_tl} - \clist_map_inline:nn{#1}{\ocgxii_vp_map_func:nN{##1}#2} + \clist_map_inline:nn{#1}{\ocgxii_ocmd_expression_parser:nN{##1}#2} \tl_put_right:Nx#2{\g_ocgxii_right_bracket_tl} + \bool_set_false:N\l_ocgxii_vp_open_bool } \cs_new_protected_nopar:Nn\ocgxii_vp_anyon:nN{ + \bool_set_true:N\l_ocgxii_vp_open_bool \tl_gput_right:Nx#2{/P/AnyOn/OCGs~\g_ocgxii_left_bracket_tl} - \clist_map_inline:nn{#1}{\ocgxii_vp_map_func:nN{##1}#2} + \clist_map_inline:nn{#1}{\ocgxii_ocmd_expression_parser:nN{##1}#2} \tl_gput_right:Nx#2{\g_ocgxii_right_bracket_tl} + \bool_set_false:N\l_ocgxii_vp_open_bool } \cs_new_protected_nopar:Nn\ocgxii_vp_anyoff:nN{ + \bool_set_true:N\l_ocgxii_vp_open_bool \tl_gput_right:Nx#2{/P/AnyOff/OCGs~\g_ocgxii_left_bracket_tl} - \clist_map_inline:nn{#1}{\ocgxii_vp_map_func:nN{##1}#2} + \clist_map_inline:nn{#1}{\ocgxii_ocmd_expression_parser:nN{##1}#2} \tl_gput_right:Nx#2{\g_ocgxii_right_bracket_tl} + \bool_set_false:N\l_ocgxii_vp_open_bool } \cs_new_protected_nopar:Nn\ocgxii_vp_alloff:nN{ + \bool_set_true:N\l_ocgxii_vp_open_bool \tl_gput_right:Nx#2{/P/AllOff/OCGs~\g_ocgxii_left_bracket_tl} - \clist_map_inline:nn{#1}{\ocgxii_vp_map_func:nN{##1}#2} + \clist_map_inline:nn{#1}{\ocgxii_ocmd_expression_parser:nN{##1}#2} \tl_gput_right:Nx#2{\g_ocgxii_right_bracket_tl} + \bool_set_false:N\l_ocgxii_vp_open_bool } -\cs_new_protected_nopar:Nn\ocgxii_vp_map_func:nN{ +% policy to expression conversion +\cs_new_protected_nopar:Nn\ocgxii_ocmd_make_equiv_ve:nN{ + \int_zero:N\l_ocgxii_ve_cnt_int + \tl_clear_new:N#2 + \clist_map_inline:nn{#1}{\ocgxii_omcd_convert_vp:nN{##1}#2} +} +\cs_new_protected_nopar:Nn\ocgxii_omcd_convert_vp:nN{ \cs_set_eq:NN\AllOn \ocgxii_vp_check:n \cs_set_eq:NN\AnyOn \ocgxii_vp_check:n \cs_set_eq:NN\AnyOff\ocgxii_vp_check:n \cs_set_eq:NN\AllOff\ocgxii_vp_check:n - \tl_if_exist:cTF{ocgx2.ocg.#1}{ - \tl_put_right:Nx#2{~\tl_use:c{ocgx2.ocg.#1}} - }{ - \tl_if_exist:cTF{ocgxii_#1}{ - \str_if_eq:eeTF{\tl_use:c{ocgxii_#1}}{VisPol}{ - \msg_error:nnxx{ocgx2}{generic~msg}{ - Visibility~policy~commands~cannot~be~nested.~For~more~complex~ - visibilty~relations,~consider~using~a~visibility~expression. - }{\g_ocgxii_help_msg_tl} - }{ - \msg_error:nnxx{ocgx2}{generic~msg}{ - Visibility~policy~and~expression~commands~cannot~be~mixed. - }{\g_ocgxii_help_msg_tl} + \cs_set_eq:NN\Not\ocgxii_ve_check:n + \cs_set_eq:NN\And\ocgxii_ve_check:n + \cs_set_eq:NN\Or \ocgxii_ve_check:n + \tl_if_exist:cT{ocgxii_#1}{ + \str_case_e:nn{\tl_use:c{ocgxii_#1}}{ + {VisExpr}{ + \int_incr:N\l_ocgxii_ve_cnt_int + \tl_set:Nn#2{#1} } - }{ - \msg_warning:nnx{ocgx2}{undefined~OCG}{#1} - \tl_if_exist:NF\g_ocgxii_refundefwarned_tl{ - \tl_new:N\g_ocgxii_refundefwarned_tl - \AtEndDocument{\msg_warning:nn{ocgx2}{undefined~OCGs}} + {VisPol}{ + \int_compare:nNnT{\l_ocgxii_ve_cnt_int}={0}{ + \cs_set_eq:NN\AllOn \ocgxii_allon_to_ve:n + \cs_set_eq:NN\AnyOn \ocgxii_anyon_to_ve:n + \cs_set_eq:NN\AnyOff\ocgxii_anyoff_to_ve:n + \cs_set_eq:NN\AllOff\ocgxii_alloff_to_ve:n + \tl_set:No#2{#1} + } } } } } -\cs_new_protected_nopar:Nn\ocgxii_ve_start:nN{ - \tl_put_right:Nx#2{/VE~} - \cs_set_eq:NN\Not\ocgxii_ve_not:nN - \cs_set_eq:NN\And\ocgxii_ve_and:nN - \cs_set_eq:NN\Or \ocgxii_ve_or:nN - #1#2 -} +\cs_new_protected_nopar:Nn\ocgxii_allon_to_ve:n{\And{#1}} +\cs_new_protected_nopar:Nn\ocgxii_anyon_to_ve:n{\Or{#1}} +\cs_new_protected_nopar:Nn\ocgxii_anyoff_to_ve:n{\Not{\And{#1}}} +\cs_new_protected_nopar:Nn\ocgxii_alloff_to_ve:n{\Not{\Or{#1}}} +% visib. boolean expressions \cs_new_protected_nopar:Nn\ocgxii_ve_and:nN{ + \bool_set_true:N\l_ocgxii_ve_open_bool \tl_put_right:Nx#2{\g_ocgxii_left_bracket_tl/And} - \clist_map_inline:nn{#1}{\ocgxii_ve_map_func:nN{##1}#2} + \clist_map_inline:nn{#1}{\ocgxii_ocmd_expression_parser:nN{##1}#2} \tl_put_right:Nx#2{\g_ocgxii_right_bracket_tl} + \bool_set_false:N\l_ocgxii_ve_open_bool } \cs_new_protected_nopar:Nn\ocgxii_ve_or:nN{ + \bool_set_true:N\l_ocgxii_ve_open_bool \tl_put_right:Nx#2{\g_ocgxii_left_bracket_tl/Or} - \clist_map_inline:nn{#1}{\ocgxii_ve_map_func:nN{##1}#2} + \clist_map_inline:nn{#1}{\ocgxii_ocmd_expression_parser:nN{##1}#2} \tl_put_right:Nx#2{\g_ocgxii_right_bracket_tl} + \bool_set_false:N\l_ocgxii_ve_open_bool } \cs_new_protected_nopar:Nn\ocgxii_ve_not:nN{ + \bool_set_true:N\l_ocgxii_ve_open_bool % only one item allowed in \Not{...} argument \int_compare:nNnT{\clist_count:n{#1}}>{\c_one_int}{ \msg_error:nnnn{ocgx2}{generic~msg}{ @@ -431,36 +513,10 @@ } \int_compare:nNnT{\clist_count:n{#1}}={\c_one_int}{ \tl_put_right:Nx#2{\g_ocgxii_left_bracket_tl/Not} - \clist_map_inline:nn{#1}{\ocgxii_ve_map_func:nN{##1}#2} + \clist_map_inline:nn{#1}{\ocgxii_ocmd_expression_parser:nN{##1}#2} \tl_put_right:Nx#2{\g_ocgxii_right_bracket_tl} } -} -\cs_new_protected_nopar:Nn\ocgxii_ve_map_func:nN{ - \cs_set_eq:NN\Not\ocgxii_ve_check:n - \cs_set_eq:NN\And\ocgxii_ve_check:n - \cs_set_eq:NN\Or \ocgxii_ve_check:n - \tl_if_exist:cTF{ocgx2.ocg.#1}{%ocg reference - \tl_put_right:Nx#2{~\tl_use:c{ocgx2.ocg.#1}} - }{ - \tl_if_exist:cTF{ocgxii_#1}{ - \str_if_eq:eeTF{\tl_use:c{ocgxii_#1}}{VisExpr}{ - \cs_set_eq:NN\Not\ocgxii_ve_not:nN - \cs_set_eq:NN\And\ocgxii_ve_and:nN - \cs_set_eq:NN\Or \ocgxii_ve_or:nN - #1#2 - }{ - \msg_error:nnxx{ocgx2}{generic~msg}{ - Visibility~policy~and~expression~commands~cannot~be~mixed. - }{\g_ocgxii_help_msg_tl} - } - }{ - \msg_warning:nnx{ocgx2}{undefined~OCG}{#1} - \tl_if_exist:NF\g_ocgxii_refundefwarned_tl{ - \tl_new:N\g_ocgxii_refundefwarned_tl - \AtEndDocument{\msg_warning:nn{ocgx2}{undefined~OCGs}} - } - } - } + \bool_set_false:N\l_ocgxii_ve_open_bool } \cs_new_protected_nopar:Nn\ocgxii_ve_check:n{VisExpr} \tl_set:cn{ocgxii_VisExpr}{VisExpr} @@ -468,6 +524,44 @@ \tl_set:cn{ocgxii_VisPol}{VisPol} \tl_set:Nx\g_ocgxii_left_bracket_tl{\tl_to_str:N[} \tl_set:Nx\g_ocgxii_right_bracket_tl{\tl_to_str:N]} +\int_new:N\l_ocgxii_vp_cnt_int %number of visib. policies +\int_new:N\l_ocgxii_ve_cnt_int %number of visib. expressions +\bool_new:N\l_ocgxii_vp_open_bool %for nesting test +\bool_new:N\l_ocgxii_ve_open_bool %for nesting test +\tl_set:Nn\g_ocgxii_help_msg_tl{ + At~most~one~visibility~policy~and,~separated~by~a~comma,~at~most~one~ + visibility~expression~may~be~passed~as~the~2nd~argument~to~the~`ocmd'~ + environment.~A~visibility~ + policy~is~defined~by~one~of~\AllOn{...},~\AnyOn{...},~\AnyOff{...},~ + \AllOff{...}.~A~visibility~expression~is~a~boolean~expression~built~by~ + nesting~any~number~of~\And{...},~\Or{...},~\Not{...}~commands.~If~both~are~ + provided,~the~visibility~expression~takes~precedence~over~the~policy,~but~the~ + latter~may~be~used~as~fallback~by~non-conforming~PDF~viewers. +} +%command that builds /OC entry from open layer stack +\cs_new_nopar:Nn\ocgxii_make_oc_entry:{ + \group_begin: + \tl_gclear:N\g_ocgxii_oc_entry_tl + \tl_clear:N\l_tempa_tl + \seq_if_empty:NF\g_ocgbase_open_stack_seq{ + \seq_clear:N\l_tempa_seq + %additional level of braces around indirect PDF objects (needed for dvips) + \seq_map_inline:Nn\g_ocgbase_open_stack_seq{ + \seq_put_right:Nn\l_tempa_seq{{##1}} + } + \ocgxii_omcd_parse_argument:xN{ + \exp_not:N\And{\seq_use:Nn\l_tempa_seq{,}} + }\l_tempa_tl + \tl_gset:Nx\g_ocgxii_oc_entry_tl{/OC~<>} + } + \group_end: +} +%programmer/author command that inserts /OC << >> entry; for use in +%annotation/xobject dicts, in order to make them layer-aware +\cs_new_nopar:Nn\ocgxii_insert_oc:{\g_ocgxii_oc_entry_tl} +\cs_gset_eq:NN\ocgbase_insert_oc:\ocgxii_insert_oc: +\cs_gset_eq:NN\ocgbase@insert@oc\ocgxii_insert_oc: +\tl_new:N\g_ocgxii_oc_entry_tl \cs_new_protected_nopar:Nn\ocgxii_stack_shipout:NN{ \iow_shipout_x:Nx\@mainaux{ @@ -746,7 +840,7 @@ ]>> } /AA << - %\str_if_eq:eeF{}{ + %\str_if_eq:eeF{}{ % mouse-up % \l_ocgxii_toswitch_u_tl\l_ocgxii_toshow_u_tl\l_ocgxii_tohide_u_tl %}{ % /U <