diff options
author | Karl Berry <karl@freefriends.org> | 2019-05-24 21:20:13 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2019-05-24 21:20:13 +0000 |
commit | 08389ad18f40230695bf434e4a1a5de4f83b1862 (patch) | |
tree | 14df0a84ac7f7f8d94f84434f2de2e900d1e4398 /Master | |
parent | eae1ca2f57626195fe6deb2dc89a6aa8936c1110 (diff) |
ocgx2 (24may19)
git-svn-id: svn://tug.org/texlive/trunk@51213 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r-- | Master/texmf-dist/doc/latex/ocgx2/ChangeLog | 6 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/ocgx2/README.txt | 97 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty | 30 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty | 347 |
4 files changed, 396 insertions, 84 deletions
diff --git a/Master/texmf-dist/doc/latex/ocgx2/ChangeLog b/Master/texmf-dist/doc/latex/ocgx2/ChangeLog index 9fe8420a144..db7e8bbe97d 100644 --- a/Master/texmf-dist/doc/latex/ocgx2/ChangeLog +++ b/Master/texmf-dist/doc/latex/ocgx2/ChangeLog @@ -1,3 +1,9 @@ +2019-05-24 + * v0.41: ocgx2.sty + * v0.15: ocgbase.sty + * new: `ocmd' environment (PDF Optional content membership dictionary) + * fix: passing driver options to expl3 + 2019-01-02 * v0.40: ocgx2.sty * fix: merge request incorporated (latex3 end-of-2018 deprecations) diff --git a/Master/texmf-dist/doc/latex/ocgx2/README.txt b/Master/texmf-dist/doc/latex/ocgx2/README.txt index e1788656734..87ef4e555ef 100644 --- a/Master/texmf-dist/doc/latex/ocgx2/README.txt +++ b/Master/texmf-dist/doc/latex/ocgx2/README.txt @@ -24,15 +24,17 @@ packages and adds support for all known engines and back-ends including To enable dvipdfmx support, pass `dvipdfmx' globally as a class option. Also, it adds some minor improvements and bug fixes, such as package -options, remembering option settings of re-opened ocgs, correct behaviour +options, remembering option settings of re-opened OCGs, correct behaviour of layer switching links that were themselves placed on layers, correct -listing of (nested) ocgs in the layers tab of PDF viewers, compatibility +listing of (nested) OCGs in the layers tab of PDF viewers, compatibility with the `animate' and `media9' packages. * New features: + PDF layers extending over page breaks - + grouping PDF layers into Radio Button Groups + + OCMDs (Optional Content Membership Dictionaries) for creating layers + with complex visibility dependency + + grouping OCGs into Radio Button Groups + additional keys for the TikZ interface of package `ocgx' + re-implementing `hyperref's `ocgcolorlinks' option for creating OCG coloured links, which are printed on paper in the default @@ -43,11 +45,17 @@ with the `animate' and `media9' packages. 2. Usage ======== -\usepackage[<options>]{ocgx2} + \usepackage[<options>]{ocgx2} -\begin{ocg}[<options>]{<layer name>}{<layer id>}{<initial visibility>} - ... material to be put on a PDF layer ... -\end{ocg} + \begin{ocg}[<options>]{<layer name>}{<OCG id>}{<initial visibility>} + ... material to be put on a PDF layer ... + \end{ocg} + + \begin{ocmd}[<OCMD id>]{[<visibility policy>][,<visibility expression>]} + ... material to be put on a PDF layer ... + visibility calculated by <visibility expression> (Boolean expression) from + other OCGs visibility, or according to <visibility policy> + \end{ocmd} With <initial visibility> = ( on | true | 1 ) | ( off | false | 0 ) @@ -73,19 +81,72 @@ of the PDF viewer, automatically hides the previously visible layer. Option `radiobtngrp' can be used repeatedly for the same OCG in order to add the layer to more than one Radio Button Group. -`ocg' environments can be nested and span multiple pages. +`ocg' as well as `ocmd' environments can be nested and span multiple pages. See the `ocg-p' manual about the environment usage and the meaning of the remaining options: texdoc ocg-p -Clickable links for switching PDF layer visibility are created with: - \switchocg[<trigger>]{<layer IDs to toggle, space separated>}{<link text>} - \showocg[<trigger>]{<layer IDs to switch ON, space separated>}{<link text>} - \hideocg[<trigger>]{<layer IDs to switch OFF, space separated>}{<link text>} - \actionsocg[<trigger>]{<IDs to toggle>}{<IDs to switch ON>}{<IDs to switch OFF>}{<link text>} +3. The `ocmd' environment (Optional Content Membership Dictionary) +================================================================== + + \begin{ocmd}[<OCMD id>]{[<visibility policy>][,<visibility expression>]} + ... material to be put on a PDF layer ... + \end{ocmd} + +This environment creates a PDF layer whose visibility is determined by the +current visibilities of other OCGs in the document according to at most one +visibility policy plus at most one visibility expression. If both are given +(with a comma in between) `<visibility expression>' takes precedence over +`<visibility policy>', but the latter may serve as a fallback in older PDF +viewers. + +`<OCMD id>' is an optional identifier which can be used to re-open the same +layer with the same visibility setting at another place further down in the +document. + +A `<visibility policy>' can be _one_ of + + \AllOn{<OCG id 1>, <OCG id 2>, ...} + \AnyOn{<OCG id 1>, <OCG id 2>, ...} + \AnyOff{<OCG id 1>, <OCG id 2>, ...} + \AllOff{<OCG id 1>, <OCG id 2>, ...} + +All four directives take a list of OCG ids from wich the OCMD visibility is +calculated. If the condition represented by the policy is met, the content +associated with the OCMD is shown. The listed OCGs can be defined anywhere in +the document. These directives can neither be combined nor nested in order to +define the policy. Thus, a visibility policy has limited capabilities. + +A `<visibility expression>' is much more flexible than a policy. Arbitrarily +complex visibility relationships can be formulated, based on the Boolean +functions + + \And{<item a>, <item b>, ...} + \Or{<item i>, <item j>, ...} + \Not{<item n>} + +In the argument list, items represent OCG ids and 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 +and policy directives cannot be intermixed. + +As a trivial example, the visibility expression equivalent of the policy +directive `\AllOff{...}' is written as `\Not{ \Or{ ... } }'. + + +4. Clickable links for switching PDF layer visibility +===================================================== + +The available commands are + + \switchocg[<trigger>]{<OCG ids to toggle, space separated>}{<link text>} + \showocg[<trigger>]{<OCG ids to switch ON, space separated>}{<link text>} + \hideocg[<trigger>]{<OCG ids to switch OFF, space separated>}{<link text>} + \actionsocg[<trigger>]{<ids to toggle>}{<ids to switch ON>}{<ids to switch OFF>}{<link text>} For details about their usage, read the `ocgx' package manual: @@ -98,16 +159,16 @@ the commands listed above. Choose one of onmousenter, onmouseexit, onmousedown, onmouseup, onmouseall for <trigger>. In order to listen to more than one mouse event, use -`onmouseall'. Layer IDs in the mandatory argument(s) must then be grouped with +`onmouseall'. Layer ids in the mandatory argument(s) must then be grouped with commas as follows: <mouse-enter group>, <mouse-exit group>, <mouse-down group>, <mouse-up group> Any of these groups may be left empty in order to configure only some -mouse triggers. Inside the groups, layer IDs are separated by space. +mouse triggers. Inside the groups, OCG ids are separated by space. -3. Package option `ocgcolorlinks' +5. Package option `ocgcolorlinks' ================================= Is a re-implementation of the same `hyperref' option for creating OCG- @@ -133,7 +194,7 @@ For example: \ocglinkprotect{\includegraphics{ctan-lion}}!} -4. Usage with TikZ +5. Usage with TikZ ================== `ocgx2' uses code from file `tikzlibraryocgx.code.tex' by P. Gaborit to @@ -157,7 +218,7 @@ their usage: The key `/tikz/ocg/opts' was added to the list in section `How to add TikZ scopes into OCGs' in the `ocgx' manual: - /tikz/ocg/opts={<ocg options>} + /tikz/ocg/opts={<OCG options>} It allows passing `ocg'-environment options (`viewocg', `printocg', `exportocg', `showingui', `radiobtngrp') to the TikZ scope. diff --git a/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty b/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty index b0113bf270a..d30786435dd 100644 --- a/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty +++ b/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty @@ -92,11 +92,19 @@ % % The Current Maintainer of this work is A. Grahn. -\RequirePackage{expl3} +%process non-detectable dvipdfmx driver for passing to expl3 +\RequirePackage{xkeyval} +\DeclareOptionX{dvipdfmx}{% + \PassOptionsToPackage{driver=dvipdfmx}{expl3} + \PassOptionsToPackage{dvipdfmx}{pdfbase} +} +\DeclareOptionX*{}\ProcessOptionsX*\relax %allow anything as an option + \RequirePackage{pdfbase} +\RequirePackage{expl3} -\def\g@ocgbase@date@tl{2018/06/07} -\def\g@ocgbase@version@tl{0.14} +\def\g@ocgbase@date@tl{2019/05/24} +\def\g@ocgbase@version@tl{0.15} \ProvidesExplPackage{ocgbase}{\g@ocgbase@date@tl}{\g@ocgbase@version@tl} {support package for ocgx2.sty} @@ -141,7 +149,7 @@ %generate RBGroups entry (radio button groups) \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}{ + \int_compare:nT{\seq_count:c{g_ocgbase_rbtn_group_#1_seq}>\c_one_int}{ \tl_put_right:Nx\l_ocgbase_rbtn_groups_tl{ ~[\seq_use:cn{g_ocgbase_rbtn_group_#1_seq}{~}] } @@ -174,14 +182,14 @@ %macro for inserting new OCG object \cs_new_protected_nopar:Nn\ocgbase_new_ocg:nnn{ \pbs_pdfobj:nnn{}{dict}{ - /Type/OCG/Name~(#1)~\str_if_eq_x:nnF{#2}{}{/Usage<<#2>>} + /Type/OCG/Name~(#1)~\str_if_eq:eeF{#2}{}{/Usage<<#2>>} } \tl_gput_right:Nx\g_ocgbase_ocgs_tl{~\pbs_pdflastobj:} \bool_if:nT{ - \str_if_eq_x_p:nn{#3}{0} || - \str_if_eq_x_p:nn{#3}{off} || - \str_if_eq_x_p:nn{#3}{false} || - \str_if_eq_x_p:nn{#3}{invisible} + \str_if_eq_p:ee{#3}{0} || + \str_if_eq_p:ee{#3}{off} || + \str_if_eq_p:ee{#3}{false} || + \str_if_eq_p:ee{#3}{invisible} }{ \ocgbase_add_to_off_list:n{\pbs_pdflastobj:} } @@ -236,7 +244,7 @@ \cs_new_protected: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{ + \str_if_eq:eeT{ \cs_if_exist_use:c{g_ocgbase_nd_\l_tempa_tl _ocg_tl} }{ \l_tempb_tl @@ -252,7 +260,7 @@ % 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}}{ + \str_if_eq:eeF{#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 diff --git a/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty b/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty index 72b51ce1940..404d849b962 100644 --- a/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty +++ b/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty @@ -15,7 +15,9 @@ % % With ocgx2, PDF layers may extend across page breaks. % -% Adds some minor improvements, such as package options, remembering option +% ocgx2 implements OCMDs (optional content membership dictionaries) +% +% 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. @@ -38,8 +40,8 @@ \RequirePackage{xparse} \RequirePackage{l3keys2e} -\def\g@ocgxii@date@tl{2019/01/02} -\def\g@ocgxii@version@tl{0.40} +\def\g@ocgxii@date@tl{2019/05/24} +\def\g@ocgxii@version@tl{0.41} \ProvidesExplPackage{ocgx2}{\g@ocgxii@date@tl}{\g@ocgxii@version@tl} {ports `ocgx' functionality to dvips+ps2pdf, xelatex and dvipdfmx} @@ -60,6 +62,8 @@ } } +\msg_set:nnn{ocgx2}{generic~msg}{#1\\#2} + \msg_set:nnn{ocgx2}{missing~package}{ Package~`#1'~must~be~loaded~before~ocgx2.\\\\ Put\\\\ @@ -122,8 +126,8 @@ 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} + \str_if_eq_p:ee{#1}{false} || + \str_if_eq_p:ee{#1}{never} }{ \bool_gset_false:N\g_ocgxii_showingui_bool }{ @@ -159,42 +163,43 @@ %re-implement ocg-p's `ocg' environment \DeclareDocumentEnvironment{ocg}{O{}mmm}{ - \ocgxii_beginocg:nnnn{#1}{#2}{#3}{#4} + \ocgxii_begin_ocg:nnnn{#1}{#2}{#3}{#4} }{ - \ocgxii_endocg: + \ocgxii_end_ocg: } -\cs_new_protected_nopar:Nn\ocgxii_beginocg:nnnn{ +\cs_new_protected_nopar:Nn\ocgxii_begin_ocg:nnnn{ \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 + \tl_set:Nx\l_ocgxii_argiv_tl{\tl_trim_spaces:n{#4}} + \tl_if_exist:cTF{ocgxii_ocg_#3}{ %re-open existing layer + \tl_set:Nx\l_tempa_tl{\tl_use:c{ocgxii_ocg_#3.opts},#1} + \tl_gset:cx{ocgxii_ocg_#3.opts}{\l_tempa_tl} %new options appended + \keys_set:nV{ocgx2/ocgenv}\l_tempa_tl \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} + \str_if_eq_p:ee{l_ocgxii_argiv_tl}{1} || + \str_if_eq_p:ee{l_ocgxii_argiv_tl}{on} || + \str_if_eq_p:ee{l_ocgxii_argiv_tl}{true} }{ - \ocgbase_del_from_off_list:n{\tl_use:c{ocgxii@#3}} + \ocgbase_del_from_off_list:n{\tl_use:c{ocgxii_ocg_#3}} }{ - \ocgbase_add_to_off_list:n{\tl_use:c{ocgxii@#3}} + \ocgbase_add_to_off_list:n{\tl_use:c{ocgxii_ocg_#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 + \tl_gset:cx{ocgxii_ocg_#3.opts}{\l_tempa_tl} + \keys_set:nV{ocgx2/ocgenv}\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:} + }{\l_ocgxii_argiv_tl} + \tl_gset:cx{ocgxii_ocg_#3}{\ocgbase_last_ocg:} \iow_now:Nx\@mainaux{ \token_to_str:N\ocgxii@newkey{ocgx2.ocg.#3}{\ocgbase_last_ocg:} } } \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}} + \str_if_eq_p:ee{\tl_use:c{ocgx2.ocg.#3}}{\tl_use:c{ocgxii_ocg_#3}} }{ \c_false_bool } @@ -204,22 +209,22 @@ \AtEndDocument{\msg_warning:nn{ocgx2}{rerun}} } } - \tl_gset:cx{ocgx2.ocg.#3}{\tl_use:c{ocgxii@#3}} + \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@#3}} + \ocgbase_add_ocg_to_radiobtn_grp:nn{##1}{\tl_use:c{ocgxii_ocg_#3}} } - \ocgbase_open_stack_push:n{\tl_use:c{ocgxii@#3}} + \ocgbase_open_stack_push:n{\tl_use:c{ocgxii_ocg_#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}} + \ocgbase_tree_node_begin:n{\tl_use:c{ocgxii_ocg_#3}} } \group_end: - \ocgbase_oc_bdc:n{\tl_use:c{ocgxii@#3}} + \ocgbase_oc_bdc:n{\tl_use:c{ocgxii_ocg_#3}} \ignorespaces } -\cs_new_protected_nopar:Nn\ocgxii_endocg:{ +\cs_new_protected_nopar:Nn\ocgxii_end_ocg:{ \unskip \ocgbase_oc_emc: \ocgbase_tree_node_end: @@ -227,6 +232,235 @@ \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_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 + } + \tl_gset:cx{ocgxii_ocmd_#1}{\pbs_pdflastobj:} + } + \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 +} +\cs_new_protected_nopar:Nn\ocgxii_end_ocmd:{ + \unskip + \ocgbase_oc_emc: + \ocgbase_open_stack_pop:N\l_trash_tl + \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{ + \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} +} +\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_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}{ + \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. + }{ + At~most~one~visibility~expression~is~allowed.~A~visibility~ + expression~is~a~boolean~expression~built~by~nesting~any~number~of~ + \And{...},~\Or{...},~\Not{...}~commands. + } + }{ + \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. + }{ + 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_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} + } + } +} +\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_new_protected_nopar:Nn\ocgxii_vp_allon:nN{ + \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} + \tl_put_right:Nx#2{\g_ocgxii_right_bracket_tl} +} +\cs_new_protected_nopar:Nn\ocgxii_vp_anyon:nN{ + \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} + \tl_gput_right:Nx#2{\g_ocgxii_right_bracket_tl} +} +\cs_new_protected_nopar:Nn\ocgxii_vp_anyoff:nN{ + \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} + \tl_gput_right:Nx#2{\g_ocgxii_right_bracket_tl} +} +\cs_new_protected_nopar:Nn\ocgxii_vp_alloff:nN{ + \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} + \tl_gput_right:Nx#2{\g_ocgxii_right_bracket_tl} +} +\cs_new_protected_nopar:Nn\ocgxii_vp_map_func: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} + } + }{ + \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_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_ve_and:nN{ + \tl_put_right:Nx#2{\g_ocgxii_left_bracket_tl/And} + \clist_map_inline:nn{#1}{\ocgxii_ve_map_func:nN{##1}#2} + \tl_put_right:Nx#2{\g_ocgxii_right_bracket_tl} +} +\cs_new_protected_nopar:Nn\ocgxii_ve_or:nN{ + \tl_put_right:Nx#2{\g_ocgxii_left_bracket_tl/Or} + \clist_map_inline:nn{#1}{\ocgxii_ve_map_func:nN{##1}#2} + \tl_put_right:Nx#2{\g_ocgxii_right_bracket_tl} +} +\cs_new_protected_nopar:Nn\ocgxii_ve_not:nN{ + % only one item allowed in \Not{...} argument + \int_compare:nNnT{\clist_count:n{#1}}>{\c_one_int}{ + \msg_error:nnnn{ocgx2}{generic~msg}{ + More~than~one~item~passed~to~\Not{...}. + }{ + Only~one~item~is~allowed. + } + } + \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} + \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}} + } + } + } +} +\cs_new_protected_nopar:Nn\ocgxii_ve_check:n{VisExpr} +\tl_set:cn{ocgxii_VisExpr}{VisExpr} +\cs_new_protected_nopar:Nn\ocgxii_vp_check:n{VisPol} +\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]} + \cs_new_protected_nopar:Nn\ocgxii_stack_shipout:NN{ \iow_shipout_x:Nx\@mainaux{ \token_to_str:N#1{ @@ -268,7 +502,7 @@ } \bool_if:nT{ !\cs_if_exist:cTF{ocgx2.oldlnkcol.\int_use:N\g_ocgxii_page_int}{ - \str_if_eq_x_p:nn{ + \str_if_eq_p:ee{ \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}{,} @@ -296,7 +530,7 @@ } \bool_if:nT{ !\cs_if_exist:cTF{ocgx2.oldstack.\int_use:N\g_ocgxii_page_int}{ - \str_if_eq_x_p:nn{ + \str_if_eq_p:ee{ \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}{,} @@ -338,7 +572,7 @@ \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 + g_pending_ocgs_on_\int_eval:n{\g_ocgxii_page_int-\c_one_int}_seq } } %the same for link colour stack @@ -346,7 +580,7 @@ \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 + g_pending_lnkcols_on_\int_eval:n{\g_ocgxii_page_int-\c_one_int}_seq } } } @@ -378,7 +612,7 @@ \cs_new_protected_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}{ + \str_case_e:nnF{\l_ocgxii_opt_tl}{ {onmouseup}{ \ocgxii_ocglist_build:Nn\l_ocgxii_u_list_tl{#2} } @@ -467,7 +701,7 @@ \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{ + \str_if_eq:eeF{ \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 @@ -488,7 +722,7 @@ /Subtype/Widget/Ff~65536/FT/Btn/BS<</W~0>> /T~(ocgx2@\int_use:N\g_ocgxii_widcount_int) %treat mouse-up as mouse-click --> handle through /A dictionary - \str_if_eq_x:nnF{}{ + \str_if_eq:eeF{}{ \l_ocgxii_toswitch_u_tl\l_ocgxii_toshow_u_tl\l_ocgxii_tohide_u_tl }{ /A <</S/SetOCGState/State [ @@ -504,7 +738,7 @@ ]>> } /AA << - %\str_if_eq_x:nnF{}{ + %\str_if_eq:eeF{}{ % \l_ocgxii_toswitch_u_tl\l_ocgxii_toshow_u_tl\l_ocgxii_tohide_u_tl %}{ % /U <</S/SetOCGState/State [ @@ -519,7 +753,7 @@ % } % ]>> %} - \str_if_eq_x:nnF{}{ % mouse-down + \str_if_eq:eeF{}{ % mouse-down \l_ocgxii_toswitch_d_tl\l_ocgxii_toshow_d_tl\l_ocgxii_tohide_d_tl }{ /D <</S/SetOCGState/State [ @@ -534,7 +768,7 @@ } ]>> } - \str_if_eq_x:nnF{}{ % mouse-enter + \str_if_eq:eeF{}{ % mouse-enter \l_ocgxii_toswitch_e_tl\l_ocgxii_toshow_e_tl\l_ocgxii_tohide_e_tl }{ /E <</S/SetOCGState/State [ @@ -549,7 +783,7 @@ } ]>> } - \str_if_eq_x:nnF{}{ % mouse-exit + \str_if_eq:eeF{}{ % mouse-exit \l_ocgxii_toswitch_x_tl\l_ocgxii_toshow_x_tl\l_ocgxii_tohide_x_tl }{ /X <</S/SetOCGState/State [ @@ -620,7 +854,7 @@ triggerocg .choices:nn = { onmouseenter, onmouseexit, onmousedown, onmouseup, allactions }{ - \str_if_eq_x:nnTF{\l_keys_choice_tl}{allactions}{ + \str_if_eq:eeTF{\l_keys_choice_tl}{allactions}{ \tl_set:Nn\l_ocgxii_trigger_tl{onmouseall} }{ \tl_set_eq:NN\l_ocgxii_trigger_tl\l_keys_choice_tl @@ -650,7 +884,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cs_new_protected:Nn\ocgxii_process_ocgref:NN{ - \str_if_eq_x:nnF{#2}{}{ + \str_if_eq:eeF{#2}{}{ \tl_if_exist:cTF{ocgx2.ocg.#2}{ \tl_put_right:Nx#1{~\tl_use:c{ocgx2.ocg.#2}} }{ @@ -663,8 +897,8 @@ } } -%command opts -\keys_define:nn{ocgx2/user}{ +%ocg environment opts +\keys_define:nn{ocgx2/ocgenv}{ viewocg .choice:, viewocg / always .code:n={ \tl_set:Nn\l_ocgxii_view_tl{/View<</ViewState/ON>>}}, @@ -693,8 +927,8 @@ 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} + \str_if_eq_p:ee{#1}{false} || + \str_if_eq_p:ee{#1}{never} }{ \bool_set_false:N\l_ocgxii_showingui_bool }{ @@ -759,10 +993,10 @@ \cs_new_protected_nopar:Nn\ocgxii_colourlink_nobreak_end:{ \color@endgroup\hbox_set_end: \mbox{ - \ocgbase_oc_bdc:n{\ocgxii@OCPrint} + \ocgbase_oc_bdc:n{\tl_use:c{ocgxii_ocg_OCPrint}} \hbox_to_zero:n{\box_use:N\l_tmpa_box\hss} \ocgbase_oc_emc: - \ocgbase_oc_bdc:n{\ocgxii@OCView} + \ocgbase_oc_bdc:n{\tl_use:c{ocgxii_ocg_OCView}} \group_begin: \exp_after:wN\HyColor@UseColor\l_ocgxii_lnkcol_tl \box_use_drop:N\l_tmpa_box @@ -845,10 +1079,10 @@ %a tiny space char should keep empty link annots from flooding the page % with link colour \hbox_overlap_left:n{\ocgxii_tiny_space_char:} - \ocgbase_oc_bdc:n{\ocgxii@OCPrint} + \ocgbase_oc_bdc:n{\tl_use:c{ocgxii_ocg_OCPrint}} \pbs_literal:nn{page}{-88888~-88888~99999~99999~re~f} \ocgbase_oc_emc: - \ocgbase_oc_bdc:n{\ocgxii@OCView} + \ocgbase_oc_bdc:n{\tl_use:c{ocgxii_ocg_OCView}} \group_begin: \exp_after:wN\HyColor@UseColor\g_ocgxii_lnkcol_tl \pbs_literal:nn{page}{-88888~-88888~99999~99999~re~f} @@ -911,22 +1145,25 @@ /Print<</PrintState/OFF>> /Export<</ExportState/OFF>> }{on} - \tl_gset:Nx\ocgxii@OCView{\ocgbase_last_ocg:} - \tl_gset:cx{ocgxii@OCView.opts}{ + \tl_gset:cx{ocgxii_ocg_OCView}{\ocgbase_last_ocg:} + %in case somebody wants to reopen with \begin{ocg}... + \tl_gset:cx{ocgxii_ocg_OCView.opts}{ showingui=never,printocg=never,exportocg=never} \ocgbase_new_ocg:nnn{OCPrint}{ /Print<</PrintState/ON>> /Export<</ExportState/ON>> }{off} - \tl_gset:Nx\ocgxii@OCPrint{\ocgbase_last_ocg:} - \tl_gset:cx{ocgxii@OCPrint.opts}{ + \tl_gset:cx{ocgxii_ocg_OCPrint}{\ocgbase_last_ocg:} + \tl_gset:cx{ocgxii_ocg_OCPrint.opts}{ showingui=never,printocg=always,exportocg=always} \ocgxii_enable_ocglinks: \iow_now:Nx\@mainaux{ - \token_to_str:N\ocgxii@newkey{ocgx2.ocg.OCView}{\ocgxii@OCView} + \token_to_str:N\ocgxii@newkey{ocgx2.ocg.OCView}{ + \tl_use:c{ocgxii_ocg_OCView}} } \iow_now:Nx\@mainaux{ - \token_to_str:N\ocgxii@newkey{ocgx2.ocg.OCPrint}{\ocgxii@OCPrint} + \token_to_str:N\ocgxii@newkey{ocgx2.ocg.OCPrint}{ + \tl_use:c{ocgxii_ocg_OCPrint}} } } }{ |