texlive[51213] Master/texmf-dist: ocgx2 (24may19)

commits+karl at tug.org commits+karl at tug.org
Fri May 24 23:20:14 CEST 2019


Revision: 51213
          http://tug.org/svn/texlive?view=revision&revision=51213
Author:   karl
Date:     2019-05-24 23:20:13 +0200 (Fri, 24 May 2019)
Log Message:
-----------
ocgx2 (24may19)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/ocgx2/ChangeLog
    trunk/Master/texmf-dist/doc/latex/ocgx2/README.txt
    trunk/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty
    trunk/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty

Modified: trunk/Master/texmf-dist/doc/latex/ocgx2/ChangeLog
===================================================================
--- trunk/Master/texmf-dist/doc/latex/ocgx2/ChangeLog	2019-05-24 21:20:02 UTC (rev 51212)
+++ trunk/Master/texmf-dist/doc/latex/ocgx2/ChangeLog	2019-05-24 21:20:13 UTC (rev 51213)
@@ -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)

Modified: trunk/Master/texmf-dist/doc/latex/ocgx2/README.txt
===================================================================
--- trunk/Master/texmf-dist/doc/latex/ocgx2/README.txt	2019-05-24 21:20:02 UTC (rev 51212)
+++ trunk/Master/texmf-dist/doc/latex/ocgx2/README.txt	2019-05-24 21:20:13 UTC (rev 51213)
@@ -24,15 +24,17 @@
 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,12 +45,18 @@
 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 )
 
 and <options> : viewocg = always | never | ifvisible
@@ -73,7 +81,7 @@
 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:
@@ -80,13 +88,66 @@
 
   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:
 
   texdoc ocgx
@@ -98,16 +159,16 @@
   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 @@
                     \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 @@
 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.

Modified: trunk/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty	2019-05-24 21:20:02 UTC (rev 51212)
+++ trunk/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty	2019-05-24 21:20:13 UTC (rev 51213)
@@ -92,11 +92,19 @@
 %
 % The Current Maintainer of this work is A. Grahn.
 
+%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}
-\RequirePackage{pdfbase}
 
-\def\g at ocgbase@date at tl{2018/06/07}
-\def\g at ocgbase@version at tl{0.14}
+\def\g at ocgbase@date at tl{2019/05/24}
+\def\g at ocgbase@version at tl{0.15}
 
 \ProvidesExplPackage{ocgbase}{\g at ocgbase@date at tl}{\g at ocgbase@version at 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

Modified: trunk/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty	2019-05-24 21:20:02 UTC (rev 51212)
+++ trunk/Master/texmf-dist/tex/latex/ocgx2/ocgx2.sty	2019-05-24 21:20:13 UTC (rev 51213)
@@ -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 at ocgxii@date at tl{2019/01/02}
-\def\g at ocgxii@version at tl{0.40}
+\def\g at ocgxii@date at tl{2019/05/24}
+\def\g at ocgxii@version at tl{0.41}
 
 \ProvidesExplPackage{ocgx2}{\g at ocgxii@date at tl}{\g at ocgxii@version at 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,35 +163,36 @@
 
 %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 at newkey{ocgx2.ocg.#3}{\ocgbase_last_ocg:}
       }
@@ -194,7 +199,7 @@
     }
     \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 at ocg@stack at 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 at ocg@stack at 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 at ocg@stack at 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 at ocg@stack at 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 at endgroup\hbox_set_end:
   \mbox{
-    \ocgbase_oc_bdc:n{\ocgxii at 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 at OCView}
+    \ocgbase_oc_bdc:n{\tl_use:c{ocgxii_ocg_OCView}}
     \group_begin:
       \exp_after:wN\HyColor at 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 at 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 at OCView}
+      \ocgbase_oc_bdc:n{\tl_use:c{ocgxii_ocg_OCView}}
         \group_begin:
           \exp_after:wN\HyColor at 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 at OCView{\ocgbase_last_ocg:}
-      \tl_gset:cx{ocgxii at 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 at OCPrint{\ocgbase_last_ocg:}
-      \tl_gset:cx{ocgxii at 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 at newkey{ocgx2.ocg.OCView}{\ocgxii at OCView}
+        \token_to_str:N\ocgxii at newkey{ocgx2.ocg.OCView}{
+          \tl_use:c{ocgxii_ocg_OCView}}
       }
       \iow_now:Nx\@mainaux{
-        \token_to_str:N\ocgxii at newkey{ocgx2.ocg.OCPrint}{\ocgxii at OCPrint}
+        \token_to_str:N\ocgxii at newkey{ocgx2.ocg.OCPrint}{
+          \tl_use:c{ocgxii_ocg_OCPrint}}
       }
     }
   }{



More information about the tex-live-commits mailing list