summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/ocgx2
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/ocgx2
Initial commit
Diffstat (limited to 'macros/latex/contrib/ocgx2')
-rw-r--r--macros/latex/contrib/ocgx2/ChangeLog225
-rw-r--r--macros/latex/contrib/ocgx2/README.md283
-rw-r--r--macros/latex/contrib/ocgx2/fixocgx.sty22
-rw-r--r--macros/latex/contrib/ocgx2/ocgbase.sty351
-rw-r--r--macros/latex/contrib/ocgx2/ocgx2.sty1489
5 files changed, 2370 insertions, 0 deletions
diff --git a/macros/latex/contrib/ocgx2/ChangeLog b/macros/latex/contrib/ocgx2/ChangeLog
new file mode 100644
index 0000000000..94f2402057
--- /dev/null
+++ b/macros/latex/contrib/ocgx2/ChangeLog
@@ -0,0 +1,225 @@
+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
+ `radiobtngrps' and accepting multiple RB group names passed as a
+ comma-separated list (`radiobtngrp' still available as an alias)
+
+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)
+
+2018-10-01
+ * v0.39: ocgx2.sty
+ * fix: ocgcolorlinks: simpler and better link-colour-spill prevention
+
+2018-09-27
+ * v0.38: ocgx2.sty
+ * fix: /ocglinkprotect{...} underfull box message and colour issue when
+ nested
+
+2018-09-25
+ * v0.37: ocgx2.sty
+ * new: /tikz/trigger ocg={...} for various mouse triggers
+
+2018-06-27
+ * v0.36: ocgx2.sty
+ * fix: code of previous fix simplified
+
+2018-06-26
+ * v0.35: ocgx2.sty
+ * fix: wrong link size of clickable paths in scaled `tikzpicture'
+
+2018-06-07
+ * v0.34: ocgx2.sty
+ * v0.14: ocgbase.sty
+ * fix: many cs now def'ed `protected'; adjustments after migration to GitLab
+
+2018-04-06
+ * v0.33: ocgx2.sty
+ * v0.13: ocgbase.sty
+ * fix: documentation section in ocgbase.sty
+
+2017-09-29
+ * v0.32: ocgx2.sty
+ * v0.12: ocgbase.sty
+ * fix: \ocglinkprotect improved
+
+2017-09-19
+ * v0.31: ocgx2.sty
+ * fix: colour flooding caused by empty links with XeTeX driver and
+ `ocgcolorlinks' option
+
+2017-09-14
+ * v0.30: ocgx2.sty
+ * v0.11: ocgbase.sty
+ * fix: link size (XeTeX driver) with `ocgcolorlinks' option set;
+ OCG switching links in Evince viewer now working; correct listing of
+ nested OCGs in layer tree (`Layers' navigation panel in the gui)
+
+2017-06-08
+ * v0.29: ocgx2.sty
+ * fix: wrong box number in internal macro, ocgcolorlinks broken for dvips
+
+2017-06-07
+ * v0.28: ocgx2.sty
+ * fix: hotfix from v0.27 replaced
+
+2017-06-07
+ * v0.27: ocgx2.sty
+ * fix: hotfix to cope with a change of \hbox:n in expl3 [2017/05/13]
+
+2017-05-12
+ * v0.26: ocgx2.sty
+ * fix: OCView, OCPrint (ocgcolorlinks related OCGs) settings saved for
+ possible re-opening by the user
+
+2017-04-25
+ * v0.25: ocgx2.sty
+ * new:OCG switching links (\showocg, \hideocg etc.) with hyperref look
+ & feel if hyperref is loaded (link border or colorlinks/ocgcolorlinks)
+
+2017-03-30
+ * v0.24: ocgx2.sty
+ * fix: \ocglinkprotect{...} messing up the graphics state (CTM)
+
+2017-03-30
+ * v0.23: ocgx2.sty
+ * v0.10: ocgbase.sty
+ * fix: nested ocgcolorlinks over multiple pages
+
+2017-03-26
+ * v0.22: ocgx2.sty
+ * fix: nested ocgcolorlinks
+
+2017-03-23
+ * v0.21: ocgx2.sty
+ * v0.9: ocgbase.sty
+ * fix: error when building document with nested OCGs
+ * new: ocgcolorlinks extending over line and page breaks
+
+2017-03-16
+ * v0.20: ocgx2.sty
+ * v0.8: ocgbase.sty
+ * fix: compatibility with other pkgs (pdfbase, xsavebox, media9, animate)
+
+2017-03-09
+ * v0.19: ocgx2.sty
+ * v0.7: ocgbase.sty
+ * fix: minor code fixes
+
+2017-03-07
+ * v0.18: ocgx2.sty
+ * fix: workaround for A-Reader bug when placing OCG switches on OCGs
+
+2016-03-22
+ * v0.17: ocgx2.sty
+ * new: option `ocgcolorlinks', enables OCG colour links for hyperref package
+
+2016-03-11
+ * v0.16: ocgx2.sty
+ * v0.6: ocgbase.sty
+ * fix: minor adjustments
+
+2016-01-29
+ * v0.15: ocgx2.sty
+ * fix: adjusted `atendvi'-related warning message
+
+2015-12-07
+ * v0.14: ocgx2.sty
+ * v0.5: ocgbase.sty
+ * fix: `0' and `1' could not be used for setting initial
+ visibility; \actionsocg macro caused compilation error when used
+ without optional argument
+
+2015-12-03
+ * v0.13: ocgx2.sty
+ * fix: bug occasionally creating wrong OCG listing in the layers
+ tab of the pdf viewer in connection with nested OCGs
+ * new: parameter `opts' added to TikZ style `ocg'
+
+2015-11-26
+ * v0.12: ocgx2.sty
+ * v0.4: ocgbase.sty
+ * fix: last argument of `ocg' environment (initial visibility)
+ had no effect when re-opening an OCG
+
+2015-11-23
+ * v0.11: ocgx2.sty
+ * v0.3: ocgbase.sty
+ * new: PDF layers spanning multiple pages
+
+2015-11-02
+ * v0.10: ocgx2.sty
+ * v0.2: ocgbase.sty
+ * new: commands \ocgbase@oc@bdc, \ocgbase_oc_bdc:n and \ocgbase@oc@emc,
+ \ocgbase_oc_emc: for marking optional content in content streams
+
+2015-10-28
+ * v0.9: ocgx2.sty
+ * v0.1: ocgbase.sty
+ * new: Environment option `radiobtngrp' (adding layers to Radio Button
+ Groups), option `showingui' as a synonym for `listintoolbar';
+ code restructured for better maintenance (new file ocgbase.sty)
+
+2015-09-11
+ * v0.8
+ * fix: missing option processing for ocg-p command replacements
+ (\toggleocgs, \showocgs etc.)
+
+2015-07-20
+ * v0.7
+ * fix: expl3-related adjustments
+
+2015-06-19
+ * v0.6a
+ * fix: typos fixed
+
+2015-06-18
+ * v0.6
+ * new: package renamed to `ocgx2'; no more dependency on ocgx and ocg-p
+ packages
+ * new: options `viewocg', `printocg', `exportocg', `listintoolbar' also
+ available as package options
+ * new: package-only option `tikz' enables P. Gaborit's `ocgx' TikZ library
+
+2015-06-15
+ * v0.5
+ * Fix: OCG ID lists with leading/trailings spaces passed as
+ argument to the OCG visibilty setting commands caused an error; the same
+ with empty arguments.
+ Improved behaviour of visibilty setting links that are themselves
+ part of OCGs.
+
+2015-03-16
+ * v0.4
+ * Fix: no more PS specials from `ocg-p.sty' in dvipdfmx mode
+
+2015-03-11
+ * v0.3
+ * New: ocg environment option `viewocg=always|never|ifvisible' added;
+ macro \fxocg@insert@OC allows package authors to insert
+ /OC <<OCMD with currently open OCGs>> entries into (suitable) pdf objects,
+ i. e. XObjects & Annotations, to make them PDF-layer aware.
+ * Fix: dead tikz-generated ocg buttons (from tikzlibraryocgx.code.tex) with
+ dvipdfmx/xelatex
+
+2015-01-26
+ * v0.2
+ * Fix: It was not possible to reference an OCG before defining it.
+
+2015-01-23
+ * v0.1
+ * New: initial release as `fixocgx'
diff --git a/macros/latex/contrib/ocgx2/README.md b/macros/latex/contrib/ocgx2/README.md
new file mode 100644
index 0000000000..e8b100e0cd
--- /dev/null
+++ b/macros/latex/contrib/ocgx2/README.md
@@ -0,0 +1,283 @@
+# The `ocgx2` LaTeX Package
+
+© 2015--`\today`, Alexander Grahn
+
+https://gitlab.com/agrahn/ocgx2
+
+## Introduction
+
+This package serves as a drop-in replacement for the already existing packages
+[**`ocgx`**](https://ctan.org/pkg/ocgx) by Paul Gaborit and
+[**`ocg-p`**](https://ctan.org/pkg/ocg-p) by Werner Moshammer for the creation of PDF
+Layers.
+
+It re-implements the functionality of the **`ocg`**, **`ocgx`** and **`ocg-p`**
+packages and adds support for all known engines and back-ends including
+
+* LaTeX &rArr; dvips &rArr; ps2pdf/Distiller
+* (Xe)LaTeX &rArr; (x)dvipdfmx
+* pdfLaTeX, LuaLaTeX
+
+To enable dvipdfmx support, pass **`dvipdfmx`** globally as a class option.
+
+Also, it adds some features, improvements and bug fixes, such as package
+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 with the
+`animate` and `media9` packages, a re-implementation of **`hyperref`**'s
+**`ocgcolorlinks`** option.
+
+----
+
+## New features
+
+* layers extending across **page breaks**
+* **OCMD**s (Optional Content Membership Dictionaries) for creating layers with
+ complex visibility dependency
+* grouping OCGs into **Radio Button Groups** (`ocg` environment option
+ **`radiobtngrps=...`**)
+* additional keys for the TikZ interface of package `ocgx`
+* re-implementing **`ocgcolorlinks`** option of package **`hyperref`** for links
+ that wrap around line and page breaks
+
+----
+
+## Usage
+
+````latex
+\usepackage[<options>]{ocgx2}
+````
+
+````latex
+\begin{ocg}[<options>]{<layer name>}{<OCG id>}{<initial visibility>}
+ ... material to be put on a PDF layer ...
+\end{ocg}
+````
+`<layer name>` is the name shown in the PDF viewer's "Layers" panel,
+`<OCG id>` is an identifier used for referencing the layer elsewhere in the
+document (e. g. layer switching buttons, visibility configuration of an `ocmd`
+environment, re-opening the OCG at another place using the `ocg` environment).
+
+`<initial visibility>` is `on`, `true`, `1` or `off`, `false`, `0`.
+
+````latex
+\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}
+````
+
+Package and `ocg` environment options:
+````latex
+viewocg = always | never | ifvisible
+printocg = always | never | ifvisible
+exportocg = always | never | ifvisible
+
+showingui = true | false
+radiobtngrps = {<group name 1>[,<group name 2>[, ...]]}
+tikz
+ocgcolorlinks
+````
+
+**Options not in** `ocgx`, `ocg-p`:
+
+* `showingui` (to be preferred over `listintoolbar` of `ocgx/ocg-p`)
+* `radiobtngrps = {<group name>, ...}` (comma-separated strings; environment-only
+ option)
+* `tikz` (package-only option; enable TikZ styles, see below)
+* `ocgcolorlinks` (package-only option, see below)
+
+Package options have global scope. Environment options override package options
+locally.
+
+OCGs can be added to one or multiple **Radio Button Groups** using the new
+option `radiobtngrps`. From all OCGs within a Radio Button Group only *one*
+can be enabled at a time. Enabling an OCG, e. g. in the Layers tab of the PDF
+viewer, automatically hides the previously visible OCG in the group. An OCG
+can be added to multiple Radio Button Groups, passing a comma-separated list of
+group names. This list must be enclosed in braces, `{...}`.
+
+`ocg` as well as `ocmd` environments can be nested and span multiple pages.
+
+See the
+[`ocg-p` manual](http://mirrors.ctan.org/macros/latex/contrib/ocg-p/ocg-p.pdf#subsection.2.3)
+about the `ocg` environment usage and the meaning of the remaining options.
+
+----
+
+## The **`ocmd`** environment (Optional Content Membership Dictionary)
+
+````latex
+\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
+
+````latex
+\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
+
+````latex
+\And{<item a>, <item b>, ...}
+\Or{<item i>, <item j>, ...}
+\Not{<item n>}
+````
+In the argument list, items represent OCG/OCMD 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/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
+directive `\AllOff{...}` is written as `\Not{ \Or{ ... } }`.
+
+----
+
+## Clickable links for switching PDF layer visibility
+
+These are the available commands:
+````latex
+\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` manual](http://mirrors.ctan.org/macros/latex/contrib/ocgx/ocgx-manual-en.pdf#subsection.1.2).
+
+By default, links are triggered on mouse-click. Other triggers are possible
+with `ocgx2`. For this, `ocgx2` provides the optional argument `[<trigger>]` to
+the commands listed above. Choose one of
+````latex
+ onmousenter, onmouseexit, onmousedown, onmouseup, onmouseall
+````
+for `<trigger>`. In order to listen to more than one mouse event, use
+`onmouseall`. OCG ids in the mandatory argument(s) must then be grouped with
+commas as follows:
+````latex
+ <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
+triggers. Inside the groups, OCG ids are separated by spaces.
+
+----
+
+## Package option `ocgcolorlinks`
+
+Is a re-implementation of the same `hyperref` option for creating OCG-
+coloured links, which are printed on paper in the default text colour.
+````latex
+\usepackage{hyperref} % do NOT set [ocgcolorlinks] here!
+\usepackage[ocgcolorlinks]{ocgx2}
+````
+Unlike the original `hyperref` implementation, OCG-coloured links are
+now allowed to extend over **line** and **page breaks**. Moreover, with
+pdfLaTeX/LuaLaTeX, OCG coloured links can be **nested**.
+
+Breakable OCG-coloured links work best with normal text as link text. If the
+link text is mixed with graphical content, such as from external files or
+inline graphics (e. g. TikZ) and even `\fbox`-ed text, these graphical parts
+must be enclosed in
+````latex
+\ocglinkprotect{...}
+````
+For example:
+````latex
+\href{http://ctan.org}{Visit me on \ocglinkprotect{\includegraphics{ctan-lion}}!}
+````
+
+----
+
+## Usage with TikZ
+
+Package `ocgx2` uses code from file `tikzlibraryocgx.code.tex` by P. Gaborit to
+enable TikZ styles for creating PDF Layers and clickable layer switching links
+in the `tikzpicture` context.
+
+Just say:
+
+````latex
+\usepackage[tikz]{ocgx2}
+````
+instead of
+
+````latex
+\usepackage{tikz}
+\usetikzlibrary{ocgx}
+````
+to enable these TikZ styles and read the
+[`ocgx` manual](http://mirrors.ctan.org/macros/latex/contrib/ocgx/ocgx-manual-en.pdf#subsection.1.3)
+about their usage.
+
+Package `ocgx2` adds the key `/tikz/ocg/opts` to the list in section "How to
+add TikZ scopes into OCGs" in the `ocgx` manual:
+
+````latex
+/tikz/ocg/opts={<OCG options>}
+````
+It can be used inside the `ocg` style
+
+````latex
+\begin{scope}[
+ ocg={ref=..., name=..., opts={..., ...}},
+ ...
+]
+ ...
+\end{scope}
+````
+and allows passing `ocg`-environment options (`viewocg`, `printocg`, `exportocg`,
+`showingui`, `radiobtngrps`) to the TikZ scope.
+
+The style `ocmd={...}` is another way for turning a TikZ scope into a PDF
+layer (in addition to `ocg={...}`). It has two sub-keys, `ref={...}` and
+`visibility={...}`, which have the same meaning as the optional and the
+mandatory arguments of the `ocmd` environment:
+
+````latex
+\begin{scope}[
+ ocmd={ref=..., visibility=...},
+ ...
+]
+ ...
+\end{scope}
+````
+Moreover, TikZ objects to be turned into OCG switching hyperlinks (section "How
+to transform nodes or paths into clickable links" in the `ocgx` manual) accept
+the additional key
+
+````latex
+/tikz/trigger ocg = onmousenter | onmouseexit | onmousedown | onmouseup | onmouseall
+````
+which makes them listen to various mouse events, as explained above.
+
+----
+
+## License
+
+This material is subject to the [LaTeX Project Public License](http://mirrors.ctan.org/macros/latex/base/lppl.txt).
+
diff --git a/macros/latex/contrib/ocgx2/fixocgx.sty b/macros/latex/contrib/ocgx2/fixocgx.sty
new file mode 100644
index 0000000000..256a71b2e0
--- /dev/null
+++ b/macros/latex/contrib/ocgx2/fixocgx.sty
@@ -0,0 +1,22 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% fixocgx.sty
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\usepackage{expl3}
+
+\ExplSyntaxOn
+
+\msg_interrupt:nnn{Package~`fixocgx':}{
+ This~package~is~obsolete~and~replaced~by~package~`ocgx2'.\\\\
+ Remove\\\\
+ \space\space\string\usepackage{ocgx}\\
+ \space\space\string\usepackage{fixocgx}\\\\
+ from~and~add\\\\
+ \space\space\string\usepackage{ocgx2}\\\\
+ to~the~document~preamble.
+}{
+ Read~the~manual~(`texdoc~ocgx2')~for~further~information.
+}
+
+\ExplSyntaxOff
diff --git a/macros/latex/contrib/ocgx2/ocgbase.sty b/macros/latex/contrib/ocgx2/ocgbase.sty
new file mode 100644
index 0000000000..fd1abcfc3a
--- /dev/null
+++ b/macros/latex/contrib/ocgx2/ocgbase.sty
@@ -0,0 +1,351 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ocgbase.sty
+%
+% low-level macros for OCG creation, marking optional content and
+% for managment of global (document-wide) OCG related lists;
+%
+% (automatic) OCG configuration in the PDF catalog
+%
+% Copyright 2015--\today, Alexander Grahn
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Support package for ocgx2.sty, media9.sty, animate.sty
+%
+% Supported workflows:
+%
+% pdflatex, lualatex
+% latex-->dvips-->ps2pdf or Distiller
+% latex-->dvipdfmx
+% xelatex
+%
+% for `dvipdfmx', set it as document class option
+%
+%
+% Commands defined:
+%
+% \ocgbase_new_ocg:nnn
+% \ocgbase@new@ocg (LaTeX2e version)
+% #1: name (as shown in the Layers Tab of the Reader GUI)
+% #2: usage dict (may be empty), see PDF reference:
+% http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/
+% pdf_reference_1-7.pdf#G9.3858276
+% #3: initial visibility (1|0|true|false|on|off|visible|invisible)
+%
+% \ocgbase_last_ocg:
+% \ocgbase@last@ocg (LaTeX2e version)
+% inserts ID of PDF object created during most recent call of
+% \ocgbase_new_ocg:nnn
+%
+% --------
+%
+% \ocgbase_tree_node_begin:n
+% \ocgbase_tree_node_end:
+% \ocgbase@tree@node@begin (LaTeX2e versions)
+% \ocgbase@tree@node@end
+% #1: OCG PDF object
+% macro pair (begin and end) for inserting OCG object and its children
+% into Order hierarchy (shown as tree structure in the viewers `Layers' tab
+%
+% --------
+%
+% \ocgbase_add_to_off_list:n
+% \ocgbase@add@to@off@list (LaTeX2e version)
+% #1: PDF object ID of OCG
+% macro for setting initial visibility to `off'
+%
+% --------
+%
+% \ocgbase_del_from_off_list:n
+% \ocgbase@del@from@off@list (LaTeX2e version)
+% #1: PDF object ID of OCG
+% macro for setting initial visibility to `on'
+%
+% --------
+%
+% \ocgbase_add_ocg_to_radiobtn_grp:nn
+% \ocgbase@add@ocg@to@radiobtn@grp
+% add OCG #2 (obj ref) to radio button group `#1' (string),
+%
+% --------
+%
+% \ocgbase_oc_bdc:n
+% \ocgbase@oc@bdc
+% #1: OCG obj ref
+% mark begin of optional content belonging to OCG #1 in the current
+% content stream
+%
+% \ocgbase_oc_emc:
+% \ocgbase@oc@emc
+% mark end of optional content in the current content stream
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License.
+%
+% The latest version of this license is in
+% http://mirrors.ctan.org/macros/latex/base/lppl.txt
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% 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}
+
+\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}
+
+\msg_set:nnnn{ocgbase}{support~outdated}{
+ Support~package~`#1'~too~old.
+}{
+ Get~an~up~to~date~version~of~`#1'.\\
+ Aborting.
+}
+\@ifpackagelater{pdfbase}{2017/09/29}{}{
+ \msg_error:nnn{ocgbase}{support~outdated}{pdfbase.sty}
+ \tex_endinput:D
+}
+
+\tl_new:N\g_ocgbase_ocgs_tl %takes ocg object refs
+\seq_new:N\g_ocgbase_offocgs_seq
+
+\pbs_at_end_dvi:n{
+ \tl_if_empty:NF\g_ocgbase_ocgs_tl{
+ %global OCG array
+ \pbs_pdfobj:nnn{}{array}{\g_ocgbase_ocgs_tl}
+ \tl_set:Nx\l_ocgbase_ocgarray_tl{\pbs_pdflastobj:}
+ \tl_new:N\l_ocgbase_offocgentry_tl
+ %global OFF list
+ \seq_if_empty:NF\g_ocgbase_offocgs_seq{
+ \pbs_pdfobj:nnn{}{array}{\seq_use:Nn\g_ocgbase_offocgs_seq{~}}
+ \tl_set:Nx\l_ocgbase_offocgentry_tl{/OFF~\pbs_pdflastobj:}
+ }
+ %global Order list
+ \tl_new:N\l_ocgbase_ocgorderentry_tl
+ \tl_new:N\l_ocgbase_ocgorder_tl
+ \tl_if_exist:cT{g_ocgbase_nd_0_chld_tl}{
+ \ocgbase_build_order:Nn\l_ocgbase_ocgorder_tl{
+ \tl_use:c{g_ocgbase_nd_0_chld_tl}
+ }
+ }
+ \tl_if_empty:NF\l_ocgbase_ocgorder_tl{
+ \pbs_pdfobj:nnn{}{array}{\l_ocgbase_ocgorder_tl}
+ \tl_set:Nx\l_ocgbase_ocgorderentry_tl{/Order~\pbs_pdflastobj:}
+ }
+ %generate RBGroups entry (radio button groups)
+ \tl_new:N\l_ocgbase_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}{
+ \tl_put_right:Nx\l_ocgbase_rbtn_groups_tl{
+ ~[\seq_use:cn{g_ocgbase_rbtn_group_#1_seq}{~}]
+ }
+ }
+ }
+ \tl_new:N\l_ocgbase_rbgroupsentry_tl
+ \tl_if_empty:NF\l_ocgbase_rbtn_groups_tl{
+ \pbs_pdfobj:nnn{}{array}{\l_ocgbase_rbtn_groups_tl}
+ \tl_set:Nx\l_ocgbase_rbgroupsentry_tl{/RBGroups~\pbs_pdflastobj:}
+ }
+ \pbs_pdfcatalog:n{
+ /OCProperties~<<
+ /OCGs~\l_ocgbase_ocgarray_tl
+ /D~<<
+ /AS~[
+ <</Event/View /Category[/View] /OCGs~\l_ocgbase_ocgarray_tl>>
+ <</Event/Print /Category[/Print] /OCGs~\l_ocgbase_ocgarray_tl>>
+ <</Event/Export/Category[/Export]/OCGs~\l_ocgbase_ocgarray_tl>>
+ ]
+ /BaseState/ON~\l_ocgbase_offocgentry_tl
+ \l_ocgbase_ocgorderentry_tl
+ \l_ocgbase_rbgroupsentry_tl
+ /ListMode/VisiblePages
+ >>
+ >>
+ }
+ }
+}
+
+%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:eeF{#2}{}{/Usage<<#2>>}
+ }
+ \tl_gput_right:Nx\g_ocgbase_ocgs_tl{~\pbs_pdflastobj:}
+ \bool_if:nT{
+ \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:}
+ }
+ \tl_gset:Nx\g_ocgbase_last_ocg_tl{\pbs_pdflastobj:}
+}
+
+\cs_new_nopar:Nn\ocgbase_last_ocg:{\g_ocgbase_last_ocg_tl}
+
+\int_new:N\g_ocgbase_nd_int %node id
+\seq_new:N\g_ocgbase_tree_nd_stack_seq %stack with open ocg node id
+\seq_new:N\g_ocgbase_tree_ocg_stack_seq %stack with open ocg obj number
+\seq_gpush:Nn\g_ocgbase_tree_nd_stack_seq{0} %push root node
+\seq_gpush:Nn\g_ocgbase_tree_ocg_stack_seq{null} %push root node
+
+%macro for starting OCG object (and nested children) insertion into Order
+%hierarchy (shown as tree structure in the viewers `Layers' tab
+\cs_new_protected:Nn\ocgbase_tree_node_begin:n{ % #1: OCG obj
+ %get the parent node from stack
+ \seq_get:NN\g_ocgbase_tree_nd_stack_seq\l__ocgbase_prnt_tl
+ \tl_if_exist:cTF{g_ocgbase_nd_\l__ocgbase_prnt_tl _chld_tl}{
+ %parent has >=1 children (i. e. my older siblings), traverse them
+ \tl_set:Nv\l__ocgbase_prev_sbl_tl{g_ocgbase_nd_\l__ocgbase_prnt_tl _chld_tl}
+ \tl_set:Nx\l__ocgbase_cur_ocg_tl{#1}
+ \ocgbase_traverse_siblings:NN\l__ocgbase_prev_sbl_tl\l__ocgbase_cur_ocg_tl
+ \str_if_empty:NTF\l__ocgbase_cur_ocg_tl{
+ %I am the first child of my parent to refer to OCG #1
+ \int_gincr:N\g_ocgbase_nd_int
+ \tl_set:Nx\l__ocgbase_cur_nd_tl{\int_use:N\g_ocgbase_nd_int}
+ %set myself as my next-older sibling's `next sibling'
+ \tl_gset:cV{
+ g_ocgbase_nd_\l__ocgbase_prev_sbl_tl _sbl_tl}\l__ocgbase_cur_nd_tl
+ }{
+ %there is already a sibling referring to OCG #1; no new node needs be
+ %created
+ \tl_set:NV\l__ocgbase_cur_nd_tl\l__ocgbase_prev_sbl_tl
+ }
+ }{
+ %I am the very first child of my parent
+ \int_gincr:N\g_ocgbase_nd_int
+ \tl_set:Nx\l__ocgbase_cur_nd_tl{\int_use:N\g_ocgbase_nd_int}
+ %set myself as my parent's first child
+ \tl_gset:cV{g_ocgbase_nd_\l__ocgbase_prnt_tl _chld_tl}\l__ocgbase_cur_nd_tl
+ }
+ %set the OCG I am referring to
+ \tl_gset:cx{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _ocg_tl}{#1}
+ %push current node and its associated OCG obj on the stacks
+ \seq_gpush:NV\g_ocgbase_tree_nd_stack_seq\l__ocgbase_cur_nd_tl
+ \seq_gpush:Nx\g_ocgbase_tree_ocg_stack_seq{#1}
+}
+
+%macro that ends insertion of OCG and sub-OCGs into Order tree
+\cs_new_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:eeT{
+ \cs_if_exist_use:c{g_ocgbase_nd_\l_tempa_tl _ocg_tl}
+ }{
+ \l_tempb_tl
+ }{
+ \seq_gpop:NN\g_ocgbase_tree_nd_stack_seq\g_trash_tl
+ \seq_gpop:NN\g_ocgbase_tree_ocg_stack_seq\g_trash_tl
+ }
+}
+
+% helper macro (recursive); traverses siblings to find either
+% the node which refers to the same OCG (arg #2 remains un-modified), or
+% the last sibling inserted (arg #2 is cleared);
+% the node id of the sibling found is returned in arg #1
+\cs_new:Nn\ocgbase_traverse_siblings:NN{
+ % #1: current node (in/out), #2: OCG obj (in/out)
+ \str_if_eq: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
+ }{
+ \tl_clear:N#2
+ }
+ }
+}
+
+\cs_new:Nn\ocgbase_build_order:Nn{
+ % (recursive macro)
+ % #1: tl var to which the OCG order is written (output)
+ % #2: starting node id (input; usually `1')
+ \tl_set:Nx\l__ocgbase_cur_nd_tl{#2}
+ % first, append the OCG obj the current node is referring to
+ \tl_put_right:Nx#1{~\tl_use:c{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _ocg_tl}}
+ % second, traverse the tree starting with the first child node
+ \tl_if_exist:cT{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _chld_tl}{
+ \seq_gpush:NV\g_ocgbase_tree_nd_stack_seq\l__ocgbase_cur_nd_tl
+ \tl_put_right:Nn#1{~[}
+ \ocgbase_build_order:Nn#1{
+ \tl_use:c{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _chld_tl}}
+ \tl_put_right:Nn#1{~]}
+ \seq_gpop:NN\g_ocgbase_tree_nd_stack_seq\l__ocgbase_cur_nd_tl
+ }
+ % third, traverse the tree starting with the next sibling node
+ \tl_if_exist:cT{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _sbl_tl}{
+ \ocgbase_build_order:Nn#1{
+ \tl_use:c{g_ocgbase_nd_\l__ocgbase_cur_nd_tl _sbl_tl}}
+ }
+}
+
+%macro for appending an OCG object to the global `OFF' list
+%(initial non-visibility)
+\cs_new_protected_nopar:Nn\ocgbase_add_to_off_list:n{
+ \seq_if_in:NxF\g_ocgbase_offocgs_seq{#1}{
+ \seq_gput_right:Nx\g_ocgbase_offocgs_seq{#1}
+ }
+}
+
+%macro for removing an OCG object from global `OFF' list
+%(initial non-visibility)
+\cs_new_protected_nopar:Nn\ocgbase_del_from_off_list:n{
+ \seq_if_in:NxT\g_ocgbase_offocgs_seq{#1}{
+ \ocgbase_seq_gremove_all:Nx\g_ocgbase_offocgs_seq{#1}
+ }
+}
+\cs_set_eq:NN\ocgbase_seq_gremove_all:Nn\seq_gremove_all:Nn
+\cs_generate_variant:Nn\ocgbase_seq_gremove_all:Nn{Nx}
+
+\seq_new:N\g_ocgbase_rbtn_groups_seq
+\cs_new_protected_nopar:Nn\ocgbase_add_ocg_to_radiobtn_grp:nn{
+ % #1: rbtn group name,
+ % #2: OCG obj ref
+ \seq_if_exist:cF{g_ocgbase_rbtn_group_#1_seq}{
+ \seq_new:c{g_ocgbase_rbtn_group_#1_seq}
+ \seq_gput_right:Nx\g_ocgbase_rbtn_groups_seq{#1}
+ }
+ \seq_if_in:cxF{g_ocgbase_rbtn_group_#1_seq}{#2}{
+ \seq_gput_right:cx{g_ocgbase_rbtn_group_#1_seq}{#2}
+ }
+}
+
+% OC-marked content
+\cs_new_protected_nopar:Nn\ocgbase_oc_bdc:n{\pbs_pdfbdc:nn{/OC}{#1}}
+\cs_new_protected_nopar:Nn\ocgbase_oc_emc:{\pbs_pdfemc:}
+
+%stack of PDF obj references of currently open OCGs
+\seq_new:N\g_ocgbase_open_stack_seq
+%push OCG to stack
+\cs_new_protected_nopar:Nn\ocgbase_open_stack_push:n{
+ \seq_gpush:Nx\g_ocgbase_open_stack_seq{#1}}
+%pop OCG from stack into tl
+\cs_new_protected_nopar:Nn\ocgbase_open_stack_pop:N{
+ \seq_gpop:NN\g_ocgbase_open_stack_seq#1}
+
+%l2e versions
+\cs_gset_eq:NN\ocgbase@new@ocg\ocgbase_new_ocg:nnn
+\cs_gset_eq:NN\ocgbase@last@ocg\ocgbase_last_ocg:
+\cs_gset_eq:NN\ocgbase@tree@node@begin\ocgbase_tree_node_begin:n
+\cs_gset_eq:NN\ocgbase@tree@node@end\ocgbase_tree_node_end:
+\cs_gset_eq:NN\ocgbase@add@to@off@list\ocgbase_add_to_off_list:n
+\cs_gset_eq:NN\ocgbase@del@from@off@list\ocgbase_del_from_off_list:n
+\cs_gset_eq:NN\ocgbase@add@ocg@to@radiobtn@grp\ocgbase_add_ocg_to_radiobtn_grp: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@open@stack@pop\ocgbase_open_stack_pop:N
+\cs_gset_eq:NN\ocgbase@open@stack@push\ocgbase_open_stack_push:n
diff --git a/macros/latex/contrib/ocgx2/ocgx2.sty b/macros/latex/contrib/ocgx2/ocgx2.sty
new file mode 100644
index 0000000000..dd46efcfe5
--- /dev/null
+++ b/macros/latex/contrib/ocgx2/ocgx2.sty
@@ -0,0 +1,1489 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% 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.
+%
+% 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.
+%
+% Re-implements hyperref's `ocgcolorlinks' option to produce coloured links
+% that may wrap around line breaks and page breaks.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License.
+%
+% The latest version of this license is in
+% http://mirrors.ctan.org/macros/latex/base/lppl.txt
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is A. Grahn.
+
+%process non-detectable dvipdfmx driver for passing to expl3
+\RequirePackage{xkeyval}
+\DeclareOptionX{dvipdfmx}{%
+ \PassOptionsToPackage{dvipdfmx}{ocgbase}
+ \PassOptionsToPackage{driver=dvipdfmx}{expl3}
+}
+\DeclareOptionX*{}\ProcessOptionsX*\relax %allow anything as an option
+
+\RequirePackage{xparse}
+\RequirePackage{l3keys2e}
+
+\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]{}
+ }
+ \iow_now:Nx\@mainaux{
+ \token_to_str:N\providecommand
+ \token_to_str:N\ocgxii@lnkcol@stack@on@page[2]{}
+ }
+}
+
+\msg_set:nnn{ocgx2}{generic~msg}{#1\\#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.
+}
+
+\msg_set:nnn{ocgx2}{beamer~and~ocgcolorlinks}{
+ Option~`ocgcolorlinks'~cannot~be~used~with~class~Beamer.\\\\
+ Using~`colorlinks'~instead.
+}
+
+%package opts
+%unknown package option error message
+\msg_set:nnnn{ocgx2}{unknown~package~option}{Unknown~package~option~`#1'.}{
+ 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
+\bool_new:N\g_ocgxii_showingui_bool
+\bool_new:N\l_ocgxii_showingui_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<</ViewState/ON>>}},
+ viewocg / never .code:n={
+ \tl_gset:Nn\g_ocgxii_view_tl{/View<</ViewState/OFF>>}},
+ 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<</PrintState/ON>>}},
+ printocg / never .code:n={
+ \tl_gset:Nn\g_ocgxii_print_tl{/Print<</PrintState/OFF>>}},
+ 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<</ExportState/ON>>}},
+ exportocg / never .code:n={
+ \tl_gset:Nn\g_ocgxii_export_tl{/Export<</ExportState/OFF>>}},
+ exportocg / ifvisible .code:n={\tl_gclear_new:N\g_ocgxii_export_tl},
+ exportocg .default:n={ifvisible},
+
+ showingui .choices:nn = {true,false,always,never,iffirstuse}{
+ \bool_if:nTF{
+ \str_if_eq_p:ee{#1}{false} ||
+ \str_if_eq_p:ee{#1}{never}
+ }{
+ \bool_gset_false:N\g_ocgxii_showingui_bool
+ }{
+ \bool_gset_true:N\g_ocgxii_showingui_bool
+ }
+ },
+ showingui .default:n={true},
+
+ listintoolbar .meta:n = {showingui=#1},
+ listintoolbar .default:n={true},
+
+ 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_begin_ocg:nnnn{#1}{#2}{#3}{#4}
+}{
+ \ocgxii_end_ocg:
+}
+
+\cs_new_protected_nopar:Nn\ocgxii_begin_ocg:nnnn{
+ \group_begin:
+ \ocgxii_reset_cmd_opts: % ... to the user-set package options
+ \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_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_ocg_#3}}
+ }{
+ \ocgbase_add_to_off_list:n{\tl_use:c{ocgxii_ocg_#3}}
+ }
+ }{
+ \tl_set:Nx\l_tempa_tl{#1}
+ \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
+ }{\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:}
+ }
+ }
+ \bool_if:nT{
+ !\cs_if_exist:cTF{ocgx2.ocg.#3}{
+ \str_if_eq_p:ee{\tl_use:c{ocgx2.ocg.#3}}{\tl_use:c{ocgxii_ocg_#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}}
+ }
+ }
+ \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{
+ \ocgbase_tree_node_begin:n{\tl_use:c{ocgxii_ocg_#3}}
+ }
+ \group_end:
+ \ocgbase_oc_bdc:n{\tl_use:c{ocgxii_ocg_#3}}
+ \ignorespaces
+}
+
+\cs_new_protected_nopar:Nn\ocgxii_end_ocg:{
+ \unskip
+ \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:on{#1}{#2}
+ \ignorespaces
+}{
+ \unskip
+ \ocgxii_end_ocmd:
+}
+
+\cs_new_protected_nopar:Nn\ocgxii_begin_ocmd:nn{ % #1: id,
+ \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{\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:{
+ \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_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_parse_argument:nN{##1}#2}
+}
+\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{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.
+ }
+ }{
+ \tl_put_right:Nx#2{/VE~}
+ \ocgxii_ocmd_expression_parser: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_ocmd_expression_parser:nN{#1}#2
+ }
+ }
+ }
+ }{
+ \msg_error:nnxx{ocgx2}{generic~msg}{
+ The~visibility~argument~of~the~`ocmd'~environment~cannot~be~parsed.
+ }{\g_ocgxii_help_msg_tl}
+ }
+ }
+ }
+}
+\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_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_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_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_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
+}
+% 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
+ \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}
+ }
+ {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_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_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_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}{
+ 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_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_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]}
+\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~<</Type/OCMD\l_tempa_tl>>}
+ }
+ \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{
+ \token_to_str:N#1{
+ \exp_not:N\int_use:N\g_ocgxii_page_int
+ }{\seq_use:Nn#2{,}}
+ }
+}
+
+\cs_new_protected_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_protected_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_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}{,}
+ }
+ }{
+ \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_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}{,}
+ }
+ }{
+ \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_int}_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_int}_seq
+ }
+ }
+}
+\int_new:N\g_ocgxii_page_int %abs. page counter
+
+\cs_new_protected_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_protected_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_protected: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_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_e:nnF{\l_ocgxii_opt_tl}{
+ {onmouseup}{
+ \ocgxii_ocglist_build:Nn\l_ocgxii_u_list_tl{#2}
+ }
+ {onmousedown}{
+ \ocgxii_ocglist_build:Nn\l_ocgxii_d_list_tl{#2}
+ }
+ {onmouseenter}{
+ \ocgxii_ocglist_build:Nn\l_ocgxii_e_list_tl{#2}
+ }
+ {onmouseexit}{
+ \ocgxii_ocglist_build:Nn\l_ocgxii_x_list_tl{#2}
+ }
+ {onmouseall}{
+ \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 link instead of plain (multiline)
+% Link;
+% adding optional 2nd argument -> Button Widget (non-breakable) with one of
+% various mouse triggers (`troggerocgs` option from ocg-p)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DeclareDocumentCommand\switchocg{s o m +m}{
+ \ocgxii_actionsocg:nnnnnn{#1}{#2}{#3}{}{}{#4}
+}
+
+\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}
+}
+
+\bool_new:N\l_ocgxii_mouse_triggers_bool
+\bool_new:N\l_ocgxii_nobreak_bool
+\cs_new_protected:Nn\ocgxii_actionsocg:nnnnnn{
+ \leavevmode
+ \bool_set_false:N\l_ocgxii_mouse_triggers_bool
+ \bool_set_false:N\l_ocgxii_nobreak_bool
+ % explicitly non-breakable?
+ \bool_if:nT{#1}{\bool_set_true:N\l_ocgxii_nobreak_bool}
+ %
+ %clear actions for various mouse triggers (e,d,x)
+ \tl_clear:N\l_ocgxii_toswitch_e_tl
+ \tl_clear:N\l_ocgxii_toswitch_x_tl
+ \tl_clear:N\l_ocgxii_toswitch_d_tl
+ \tl_clear:N\l_ocgxii_toshow_e_tl
+ \tl_clear:N\l_ocgxii_toshow_x_tl
+ \tl_clear:N\l_ocgxii_toshow_d_tl
+ \tl_clear:N\l_ocgxii_tohide_e_tl
+ \tl_clear:N\l_ocgxii_tohide_x_tl
+ \tl_clear:N\l_ocgxii_tohide_d_tl
+ %
+ %process *all* mouse triggers (e,d,u,x)
+ \ocgxii_ocglist_process_idlist:nn{
+ \IfValueTF{#2}{#2}{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}{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}{onmouseup}
+ }{#5}
+ \tl_set_eq:NN\l_ocgxii_tohide_e_tl\l_ocgxii_e_list_tl
+ \tl_set_eq:NN\l_ocgxii_tohide_x_tl\l_ocgxii_x_list_tl
+ \tl_set_eq:NN\l_ocgxii_tohide_d_tl\l_ocgxii_d_list_tl
+ \tl_set_eq:NN\l_ocgxii_tohide_u_tl\l_ocgxii_u_list_tl
+ %any triggers apart from mouse-up?
+ \str_if_eq: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
+ }{}{
+ \bool_set_true:N\l_ocgxii_mouse_triggers_bool
+ }
+ %
+ \bool_if:nTF{\l_ocgxii_nobreak_bool || \l_ocgxii_mouse_triggers_bool}{
+ \hbox_set:Nn\l_tmpa_box{#6}
+ \pbs_pdfannot:nnnn{
+ \dim_use:N\box_wd:N\l_tmpa_box}{
+ \dim_use:N\box_ht:N\l_tmpa_box}{
+ \dim_use:N\box_dp:N\l_tmpa_box
+ }{
+ \bool_if:NTF\l_ocgxii_mouse_triggers_bool{
+ % e,d,x mouse triggers require (non-breakable) /Widget annot with AA
+ % (additional actions) dict
+ /Subtype/Widget/Ff~65536/FT/Btn/BS<</W~0>>
+ /T~(ocgx2@\int_use:N\g_ocgxii_widcount_int)
+ %treat mouse-up as mouse-click --> handle through /A dictionary
+ \str_if_eq:eeF{}{
+ \l_ocgxii_toswitch_u_tl\l_ocgxii_toshow_u_tl\l_ocgxii_tohide_u_tl
+ }{
+ /A <</S/SetOCGState/State [
+ \str_if_eq:VnF\l_ocgxii_toswitch_u_tl{}{
+ /Toggle~\l_ocgxii_toswitch_u_tl
+ }
+ \str_if_eq:VnF\l_ocgxii_toshow_u_tl{}{
+ /ON~\l_ocgxii_toshow_u_tl
+ }
+ \str_if_eq:VnF\l_ocgxii_tohide_u_tl{}{
+ /OFF~\l_ocgxii_tohide_u_tl
+ }
+ ]>>
+ }
+ /AA <<
+ %\str_if_eq:eeF{}{ % mouse-up
+ % \l_ocgxii_toswitch_u_tl\l_ocgxii_toshow_u_tl\l_ocgxii_tohide_u_tl
+ %}{
+ % /U <</S/SetOCGState/State [
+ % \str_if_eq:VnF\l_ocgxii_toswitch_u_tl{}{
+ % /Toggle~\l_ocgxii_toswitch_u_tl
+ % }
+ % \str_if_eq:VnF\l_ocgxii_toshow_u_tl{}{
+ % /ON~\l_ocgxii_toshow_u_tl
+ % }
+ % \str_if_eq:VnF\l_ocgxii_tohide_u_tl{}{
+ % /OFF~\l_ocgxii_tohide_u_tl
+ % }
+ % ]>>
+ %}
+ \str_if_eq:eeF{}{ % mouse-down
+ \l_ocgxii_toswitch_d_tl\l_ocgxii_toshow_d_tl\l_ocgxii_tohide_d_tl
+ }{
+ /D <</S/SetOCGState/State [
+ \str_if_eq:VnF\l_ocgxii_toswitch_d_tl{}{
+ /Toggle~\l_ocgxii_toswitch_d_tl
+ }
+ \str_if_eq:VnF\l_ocgxii_toshow_d_tl{}{
+ /ON~\l_ocgxii_toshow_d_tl
+ }
+ \str_if_eq:VnF\l_ocgxii_tohide_d_tl{}{
+ /OFF~\l_ocgxii_tohide_d_tl
+ }
+ ]>>
+ }
+ \str_if_eq:eeF{}{ % mouse-enter
+ \l_ocgxii_toswitch_e_tl\l_ocgxii_toshow_e_tl\l_ocgxii_tohide_e_tl
+ }{
+ /E <</S/SetOCGState/State [
+ \str_if_eq:VnF\l_ocgxii_toswitch_e_tl{}{
+ /Toggle~\l_ocgxii_toswitch_e_tl
+ }
+ \str_if_eq:VnF\l_ocgxii_toshow_e_tl{}{
+ /ON~\l_ocgxii_toshow_e_tl
+ }
+ \str_if_eq:VnF\l_ocgxii_tohide_e_tl{}{
+ /OFF~\l_ocgxii_tohide_e_tl
+ }
+ ]>>
+ }
+ \str_if_eq:eeF{}{ % mouse-exit
+ \l_ocgxii_toswitch_x_tl\l_ocgxii_toshow_x_tl\l_ocgxii_tohide_x_tl
+ }{
+ /X <</S/SetOCGState/State [
+ \str_if_eq:VnF\l_ocgxii_toswitch_x_tl{}{
+ /Toggle~\l_ocgxii_toswitch_x_tl
+ }
+ \str_if_eq:VnF\l_ocgxii_toshow_x_tl{}{
+ /ON~\l_ocgxii_toshow_x_tl
+ }
+ \str_if_eq:VnF\l_ocgxii_tohide_x_tl{}{
+ /OFF~\l_ocgxii_tohide_x_tl
+ }
+ ]>>
+ }
+ >>
+ }{
+ %mouse-up alone may go with simple /Link annot
+ /Subtype/Link
+ /A <</S/SetOCGState
+ /State [
+ \str_if_eq:VnF{\l_ocgxii_toswitch_u_tl}{}{
+ /Toggle~\l_ocgxii_toswitch_u_tl}~
+ \str_if_eq:VnF{\l_ocgxii_toshow_u_tl}{}{/ON~\l_ocgxii_toshow_u_tl}~
+ \str_if_eq:VnF{\l_ocgxii_tohide_u_tl}{}{/OFF~\l_ocgxii_tohide_u_tl}
+ ]
+ >>
+ /Border~[0~0~0]
+ }
+ \cs_if_exist:NT\@pdfhighlight{
+ \ifx\@pdfhighlight\@empty\else/H\@pdfhighlight\fi
+ }
+ }\box_use_drop:N\l_tmpa_box
+ \bool_if:NT\l_ocgxii_mouse_triggers_bool{
+ \pbs_appendtofields:n{\pbs_pdflastann:}
+ \int_gincr:N\g_ocgxii_widcount_int
+ }
+ }{
+ %line-breakable annotation
+ \pbs_pdflink:nn{
+ /Subtype/Link
+ /A <</S/SetOCGState
+ /State [
+ \str_if_eq:VnF{\l_ocgxii_toswitch_u_tl}{}{
+ /Toggle~\l_ocgxii_toswitch_u_tl}~
+ \str_if_eq:VnF{\l_ocgxii_toshow_u_tl}{}{/ON~\l_ocgxii_toshow_u_tl}~
+ \str_if_eq:VnF{\l_ocgxii_tohide_u_tl}{}{/OFF~\l_ocgxii_tohide_u_tl}
+ ]
+ >>
+ %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
+\keys_define:nn{ocgx2/ocgpcmd}{
+ triggerocg .choices:nn = {
+ onmouseenter, onmouseexit, onmousedown, onmouseup, 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
+ }
+ }
+}
+\DeclareDocumentCommand\toggleocgs{O{} m +m}{
+ \tl_clear_new:N\l_ocgxii_trigger_tl
+ \keys_set:nn{ocgx2/ocgpcmd}{#1}
+ \switchocg*[\l_ocgxii_trigger_tl]{#2}{#3}
+}
+\DeclareDocumentCommand\showocgs{O{} m +m}{
+ \tl_clear_new:N\l_ocgxii_trigger_tl
+ \keys_set:nn{ocgx2/ocgpcmd}{#1}
+ \showocg*[\l_ocgxii_trigger_tl]{#2}{#3}
+}
+\DeclareDocumentCommand\hideocgs{O{} m +m}{
+ \tl_clear_new:N\l_ocgxii_trigger_tl
+ \keys_set:nn{ocgx2/ocgpcmd}{#1}
+ \hideocg*[\l_ocgxii_trigger_tl]{#2}{#3}
+}
+\DeclareDocumentCommand\setocgs{O{} m m m +m}{
+ \tl_clear_new:N\l_ocgxii_trigger_tl
+ \keys_set:nn{ocgx2/ocgpcmd}{#1}
+ \actionsocg*[\l_ocgxii_trigger_tl]{#2}{#3}{#4}{#5}
+}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\cs_new_protected:Nn\ocgxii_process_ocgref:NN{
+ \str_if_eq:eeF{#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}}
+ }
+ }
+ }
+}
+
+%ocg environment opts
+\keys_define:nn{ocgx2/ocgenv}{
+ viewocg .choice:,
+ viewocg / always .code:n={
+ \tl_set:Nn\l_ocgxii_view_tl{/View<</ViewState/ON>>}},
+ viewocg / never .code:n={
+ \tl_set:Nn\l_ocgxii_view_tl{/View<</ViewState/OFF>>}},
+ 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<</PrintState/ON>>}},
+ printocg / never .code:n={
+ \tl_set:Nn\l_ocgxii_print_tl{/Print<</PrintState/OFF>>}},
+ 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<</ExportState/ON>>}},
+ exportocg / never .code:n={
+ \tl_set:Nn\l_ocgxii_export_tl{/Export<</ExportState/OFF>>}},
+ exportocg / ifvisible .code:n={\tl_clear:N\l_ocgxii_export_tl},
+ exportocg .default:n={ifvisible},
+
+ showingui .choices:nn = {true,false,always,never,iffirstuse}{
+ \bool_if:nTF{
+ \str_if_eq_p:ee{#1}{false} ||
+ \str_if_eq_p:ee{#1}{never}
+ }{
+ \bool_set_false:N\l_ocgxii_showingui_bool
+ }{
+ \bool_set_true:N\l_ocgxii_showingui_bool
+ }
+ },
+ showingui .default:n={true},
+
+ listintoolbar .meta:n = {showingui=#1},
+ listintoolbar .default:n={true},
+
+ radiobtngrps .code:n = {
+ \clist_map_inline:nn{#1}{
+ \seq_if_in:NxF\l_ocgxii_rbgrps_seq{##1}{
+ \seq_put_right:Nx\l_ocgxii_rbgrps_seq{##1}
+ }
+ }
+ },
+ radiobtngrps .value_required:n = {true},
+ radiobtngrp .meta:n={radiobtngrps={#1}},
+ radiobtngrp .value_required:n = {true}
+}
+
+\cs_new_protected: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
+ \bool_set_eq:NN\l_ocgxii_showingui_bool\g_ocgxii_showingui_bool
+ %stack of radio button group names the current ocg belongs to
+ \seq_clear_new:N\l_ocgxii_rbgrps_seq
+}
+
+\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 idea
+% http://tex.stackexchange.com/a/104227;
+% with some improvements
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\cs_new_protected_nopar:Nn\ocgxii_colourlink_begin:{}
+\cs_new_protected_nopar:Nn\ocgxii_colourlink_end:{}
+\cs_new_protected_nopar:Nn\ocgxii_colourlink_nobreak_begin:{
+ \hbox_set:Nw\l_tmpa_box\color@begingroup
+ \tl_set_eq:NN\color@setgroup\group_begin:
+}
+\cs_new_protected_nopar:Nn\ocgxii_colourlink_nobreak_end:{
+ \color@endgroup\hbox_set_end:
+ \mbox{
+ \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{\tl_use:c{ocgxii_ocg_OCView}}
+ \group_begin:
+ \exp_after:wN\HyColor@UseColor\l_ocgxii_lnkcol_tl
+ \box_use_drop: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
+
+%we'll be using the downscaled space character (32) from the pzdr
+% (dingbats) font at the end of every ocgcolorlink in order to prevent
+% empty links from flooding the page with link colour
+\cs_new_nopar:Npn\ocgxii_tiny_space_char:{
+ \group_begin:
+ \font\l_tmpa_tl=pzdr~scaled~1\l_tmpa_tl\char32
+ \group_end:
+}
+
+\bool_if:nTF{\sys_if_output_dvi_p: && !\g_ocgxii_dvipdfmx_bool}{
+ % non-breakable links in dvips
+ \cs_new_protected_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_protected_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
+ }
+ }
+ \bool_if:NT\l_ocgxii_ocgcolorlinks_bool{
+ \cs_gset_nopar:Nn\ocgxii_colourlink_begin:{
+ \pbs_literal:nn{page}{q~7~Tr}
+ }
+ \cs_gset_nopar:Nn\ocgxii_colourlink_end:{
+ %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{\tl_use:c{ocgxii_ocg_OCPrint}}
+ \pbs_literal:nn{page}{-88888~-88888~99999~99999~re~f}
+ \ocgbase_oc_emc:
+ \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}
+ \group_end:
+ \ocgbase_oc_emc:
+ \pbs_literal:nn{page}{0~Tr~Q}
+ }
+ }
+}
+
+% user command for protecting graphical content (external file, inline
+% [e. g. TikZ], \fbox{...}) inside breakable ocgcolorlink
+\bool_if:NTF\l_ocgxii_ocgcolorlinks_bool{
+ \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:
+ }
+ \group_begin:
+ \cs_set_nopar:Npn\ocglinkprotect##1{##1} % in case of nesting
+ \sys_if_output_pdf:TF{
+ \leavevmode
+ \hbox_set:Nn\l_tmpb_box{#1}
+ \hbox_to_wd:nn{\box_wd:N\l_tmpb_box}{
+ \vrule~width~\c_zero_dim~height~\box_ht:N\l_tmpb_box~
+ depth~\box_dp:N\l_tmpb_box
+ \pbs_pdfxform:nnnnn{1}{0}{}{}{\l_tmpb_box}
+ \pbs_pdfrefxform:n{\pbs_pdflastxform:}
+ \hss
+ }
+ }{#1}
+ \group_end:
+ \seq_get_left:NNT\g_ocgxii_lnk_color_seq\l_tmpa_tl{
+ \ocgxii_colourlink_nobreak_end:
+ \group_end:
+ \ocgxii_colourlink_begin:
+ }
+ }
+}{
+ \DeclareDocumentCommand\ocglinkprotect{m}{#1}
+}
+
+% option ocgcolorlinks and beamer are not compatible
+\bool_if:NT\l_ocgxii_ocgcolorlinks_bool{
+ \@ifclassloaded{beamer}{
+ \bool_set_false:N\l_ocgxii_ocgcolorlinks_bool
+ \hypersetup{colorlinks}
+ \msg_warning:nn{ocgx2}{beamer~and~ocgcolorlinks}
+ }{}
+}
+
+\bool_if:NT\l_ocgxii_ocgcolorlinks_bool{
+ \@ifpackageloaded{hyperref}{
+ \Hy@colorlinkstrue
+ \AtBeginDocument{
+ \ocgbase_new_ocg:nnn{OCView}{
+ /Print<</PrintState/OFF>>
+ /Export<</ExportState/OFF>>
+ }{on}
+ \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: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}{
+ \tl_use:c{ocgxii_ocg_OCView}}
+ }
+ \iow_now:Nx\@mainaux{
+ \token_to_str:N\ocgxii@newkey{ocgx2.ocg.OCPrint}{
+ \tl_use:c{ocgxii_ocg_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}
+\cs_set_eq:NN\ocgxii@trmspc\tl_trim_spaces:N
+\ExplSyntaxOff
+\RequirePackage{tikz}
+\usetikzlibrary{calc}
+
+% helper, replaces all spaces in #1 with `_'
+\def\ocgxii@cnvspc#1{\expandafter\ocgxii@@cnvspc#1 \@nil}
+\def\ocgxii@@cnvspc#1 #2\@nil{#1\ifx\@nil#2\@nil\else_\ocgxii@@cnvspc#2\@nil\fi}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Copyright notice: The code that follows until the end of the file was
+% taken in large parts from Paul Gaborit's `tikzlibraryocgx.code.tex' with
+% some additions/fixes:
+%
+% - opts={...} inside ocg={...} allows ocg-environment options to be passed
+% to a TikZ scope
+%
+% - The style ocmd={...} is another way for turning a TikZ scope into a PDF
+% layer (in addition to ocg={...}). It has two sub-keys, ref={...} and
+% visibility={...}, which have the same meaning as the optional and the
+% mandatory arguments of the `ocmd' environment
+%
+% - TikZ objects to be turned into OCG switching links accept the additional
+% key
+%
+% trigger ocg = onmousenter | onmouseexit | onmousedown | onmouseup |
+% onmouseall
+%
+% to react to various mouse gestures
+%
+% - switching links properly sized and working in scaled tikzpictures
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\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=, % NEW
+ 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}},
+ }
+ },
+ ocmd/.style={
+ ocmd/.cd,
+ #1,
+ /tikz/execute at begin scope={%
+ \begin{ocmd}[\ocgxii@ocmdref]{\ocgxii@ocmdvisibility}%
+ },
+ /tikz/execute at end scope={\end{ocmd}},
+ /tikz/.cd
+ },
+ ocmd={
+ % parameters
+ ref/.store in=\ocgxii@ocmdref,
+ visibility/.store in=\ocgxii@ocmdvisibility,
+ % default values
+ ref=,
+ visibility=,
+ },
+ trigger ocg/.store in=\ocgxii@trigger,
+ trigger ocg/.value required,
+ switch ocg/.style={
+ postaction={
+ path picture={
+ \path (path picture bounding box.south west) coordinate (p1)
+ (path picture bounding box.north east) coordinate (p2)
+ (p1) node[inner sep=0pt,anchor=south west,outer sep=0pt] {%
+ \ifdefined\ocgxii@trigger%
+ \switchocg*[\ocgxii@trigger]{#1}{%
+ \tikz \useasboundingbox (p1) rectangle (p2);}%
+ \else%
+ \switchocg*{#1}{\tikz \useasboundingbox (p1) rectangle (p2);}%
+ \fi%
+ };
+ }
+ }
+ },
+ switch ocg with mark on/.style 2 args={
+ postaction={
+ path picture={%
+ \edef\ocgxii@argone{#1}%ocg ref for checkmark
+ \ocgxii@trmspc\ocgxii@argone%
+ \global\let\ocgxii@argone\ocgxii@argone%
+ %default ocg ref for checkmark, if nothing provided in #1
+ \xdef\ocgxii@argtwo{#2.mark}%
+ \xdef\ocgxii@argtwo{\ocgxii@cnvspc{\ocgxii@argtwo}}%
+ \begin{ocg}[showingui=false]{%
+ \ifx\ocgxii@argone\@empty\ocgxii@argtwo\else\ocgxii@argone\fi%
+ }{%
+ \ifx\ocgxii@argone\@empty\ocgxii@argtwo\else\ocgxii@argone\fi%
+ }{on}%
+ \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={%
+ \ifx\ocgxii@argone\@empty\ocgxii@argtwo\else{\ocgxii@argone}\fi\space #2%
+ }
+ }
+ },
+ switch ocg with mark off/.style 2 args={
+ postaction={
+ path picture={%
+ \edef\ocgxii@argone{#1}%ocg ref for checkmark
+ \ocgxii@trmspc\ocgxii@argone%
+ \global\let\ocgxii@argone\ocgxii@argone%
+ %default ocg ref for checkmark, if nothing provided in #1
+ \xdef\ocgxii@argtwo{#2.mark}%
+ \xdef\ocgxii@argtwo{\ocgxii@cnvspc{\ocgxii@argtwo}}%
+ \begin{ocg}[showingui=false]{%
+ \ifx\ocgxii@argone\@empty\ocgxii@argtwo\else\ocgxii@argone\fi%
+ }{%
+ \ifx\ocgxii@argone\@empty\ocgxii@argtwo\else\ocgxii@argone\fi%
+ }{off}%
+ \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={%
+ \ifx\ocgxii@argone\@empty\ocgxii@argtwo\else{\ocgxii@argone}\fi\space #2%
+ }
+ }
+ },
+ show ocg/.style={
+ postaction={
+ path picture={
+ \path (path picture bounding box.south west) coordinate (p1)
+ (path picture bounding box.north east) coordinate (p2)
+ (p1) node[inner sep=0pt,anchor=south west,outer sep=0pt] {%
+ \ifdefined\ocgxii@trigger%
+ \showocg*[\ocgxii@trigger]{#1}{%
+ \tikz \useasboundingbox (p1) rectangle (p2);}%
+ \else%
+ \showocg*{#1}{\tikz \useasboundingbox (p1) rectangle (p2);}%
+ \fi%
+ };
+ }
+ }
+ },
+ hide ocg/.style={
+ postaction={
+ path picture={
+ \path (path picture bounding box.south west) coordinate (p1)
+ (path picture bounding box.north east) coordinate (p2)
+ (p1) node[inner sep=0pt,anchor=south west,outer sep=0pt] {%
+ \ifdefined\ocgxii@trigger%
+ \hideocg*[\ocgxii@trigger]{#1}{%
+ \tikz \useasboundingbox (p1) rectangle (p2);}%
+ \else%
+ \hideocg*{#1}{\tikz \useasboundingbox (p1) rectangle (p2);}%
+ \fi%
+ };
+ }
+ }
+ },
+ actions ocg/.style n args={3}{
+ postaction={
+ path picture={
+ \path (path picture bounding box.south west) coordinate (p1)
+ (path picture bounding box.north east) coordinate (p2)
+ (p1) node[inner sep=0pt,anchor=south west,outer sep=0pt] {%
+ \ifdefined\ocgxii@trigger%
+ \actionsocg*[\ocgxii@trigger]{#1}{#2}{#3}{%
+ \tikz \useasboundingbox (p1) rectangle (p2);}%
+ \else%
+ \actionsocg*{#1}{#2}{#3}{%
+ \tikz \useasboundingbox (p1) rectangle (p2);}%
+ \fi%
+ };
+ }
+ }
+ }
+}