summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2017-09-14 21:07:39 +0000
committerKarl Berry <karl@freefriends.org>2017-09-14 21:07:39 +0000
commita6b5829b28e31661ed47531b08a01cb2864b290b (patch)
treed9f792f90aab003d82fcdd2ff3d4b01d30820818 /Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty
parentbf209a8e0ec3db9f1fd8513bdc7341357468a1c0 (diff)
ocgx2 (14sep17)
git-svn-id: svn://tug.org/texlive/trunk@45303 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty')
-rw-r--r--Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty256
1 files changed, 139 insertions, 117 deletions
diff --git a/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty b/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty
index ec2b8b9393a..9dfe301840f 100644
--- a/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty
+++ b/Master/texmf-dist/tex/latex/ocgx2/ocgbase.sty
@@ -40,11 +40,13 @@
%
% --------
%
-% \ocgbase_add_to_order_list:n
-% \ocgbase@add@to@order@list (LaTeX2e version)
-% #1: PDF object ID of OCG
-% Only OCGs added to the global `Order' list using this command will show
-% up in the Layers Tab
+% \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
%
% --------
%
@@ -82,12 +84,10 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This work may be distributed and/or modified under the
-% conditions of the LaTeX Project Public License, either version 1.3
-% of this license or (at your option) any later version.
+% conditions of the LaTeX Project Public License.
+%
% The latest version of this license is in
-% http://mirrors.ctan.org/help/Catalogue/licenses.lppl.html
-% and version 1.3 or later is part of all distributions of LaTeX
-% version 2005/12/01 or later.
+% http://mirrors.ctan.org/macros/latex/base/lppl.txt
%
% This work has the LPPL maintenance status `maintained'.
%
@@ -96,8 +96,8 @@
\RequirePackage{expl3}
\RequirePackage{pdfbase}
-\def\g@ocgbase@date@tl{2017/03/30}
-\def\g@ocgbase@version@tl{0.10}
+\def\g@ocgbase@date@tl{2017/09/14}
+\def\g@ocgbase@version@tl{0.11}
\ProvidesExplPackage{ocgbase}{\g@ocgbase@date@tl}{\g@ocgbase@version@tl}
{support package for ocgx2.sty}
@@ -114,7 +114,6 @@
}
\tl_new:N\g_ocgbase_ocgs_tl %takes ocg object refs
-\seq_new:N\g_ocgbase_ocgorder_seq
\seq_new:N\g_ocgbase_offocgs_seq
\pbs_at_end_dvi:n{
@@ -130,77 +129,28 @@
}
%global Order list
\tl_new:N\l_ocgbase_ocgorderentry_tl
- \seq_if_empty:NF\g_ocgbase_ocgorder_seq{
- %process radio button groups in the Order array
- \seq_map_inline:Nn\g_ocgbase_ocgorder_seq{
- \cs_if_exist:cT{g_ocgbase_#1_rbtn_order_seq}{
- \int_compare:nTF{\seq_count:c{g_ocgbase_#1_rbtn_groups_seq}>\c_one}{
- \int_compare:nT{\seq_count:c{g_ocgbase_#1_rbtn_order_seq}>\c_zero}{
- %remove all occurrences in Order array outside current rbtn group
- \seq_map_inline:cn{g_ocgbase_#1_rbtn_order_seq}{
- \seq_gremove_all:Nn\g_ocgbase_ocgorder_seq{##1}
- }
- }
- }{
- %ignore single-item radio button groups
- \seq_gremove_all:Nn\g_ocgbase_ocgorder_seq{#1}
- }
- }
- }
- %second sweep on Order array to generate the final Order entry
- \tl_new:N\l_ocgbase_ocgorder_tl
- \tl_set:Nn\l_ocgbase_order_item_count_tl{0}
- \seq_map_inline:Nn\g_ocgbase_ocgorder_seq{
- \tl_set:Nx\l_ocgbase_order_item_count_tl{
- \int_eval:n{\l_ocgbase_order_item_count_tl+\c_one}
- }
- \cs_if_exist:cTF{g_ocgbase_#1_rbtn_order_seq}{
- \int_compare:nT{\seq_count:c{g_ocgbase_#1_rbtn_order_seq}>\c_zero}{
- \tl_put_right:Nx\l_ocgbase_ocgorder_tl{
- ~[(#1)~\seq_use:cn{g_ocgbase_#1_rbtn_order_seq}{~}]
- }
- }
- }{
- %ordinary (non-radiobutton group) item (ocg obj ref, `[' or `]'),
- \tl_set:Nx\l_ocgbase_current_order_item_tl{#1}
- \tl_set:Nx\l_ocgbase_next_order_item_tl{
- \seq_item:Nn\g_ocgbase_ocgorder_seq{
- \l_ocgbase_order_item_count_tl+\c_one
- }
- }
- \tl_set:Nx\l_ocgbase_prev_order_item_tl{
- \seq_item:Nn\g_ocgbase_ocgorder_seq{
- \l_ocgbase_order_item_count_tl-\c_one
- }
- }
- \bool_if:nF{ %avoid empty nesting groups
- \str_if_eq_p:Vn\l_ocgbase_current_order_item_tl{[} &&
- \str_if_eq_p:Vn\l_ocgbase_next_order_item_tl{]}
- ||
- \str_if_eq_p:Vn\l_ocgbase_current_order_item_tl{]} &&
- \str_if_eq_p:Vn\l_ocgbase_prev_order_item_tl{[}
- }{\tl_put_right:Nn\l_ocgbase_ocgorder_tl{~#1}}
- }
- }
- \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:}
+ \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_rbgroups_tl
- \seq_map_inline:Nn\g_ocgbase_ocgorder_seq{
- \cs_if_exist:cT{g_ocgbase_#1_rbtn_groups_seq}{
- \int_compare:nT{\seq_count:c{g_ocgbase_#1_rbtn_groups_seq}>\c_one}{
- \tl_put_right:Nx\l_ocgbase_rbgroups_tl{
- ~[\seq_use:cn{g_ocgbase_#1_rbtn_groups_seq}{~}]
- }
+ \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}{
+ \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_rbgroups_tl{
- \pbs_pdfobj:nnn{}{array}{\l_ocgbase_rbgroups_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{
@@ -241,10 +191,98 @@
\cs_new_nopar:Nn\ocgbase_last_ocg:{\g_ocgbase_last_ocg_tl}
-%macro for appending OCG object to global `Order' list
-% in Layers Tab of the GUI
-\cs_new_nopar:Nn\ocgbase_add_to_order_list:n{
- \seq_gput_right:Nx\g_ocgbase_ocgorder_seq{#1}
+\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: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: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{
+ \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; 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_x:nnF{#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{
+ % #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
@@ -265,31 +303,17 @@
\cs_set_eq:NN\ocgbase_seq_gremove_all:Nn\seq_gremove_all:Nn
\cs_generate_variant:Nn\ocgbase_seq_gremove_all:Nn{Nx}
-\cs_new_nopar:Nn\ocgbase_add_ocg_to_radiobtn_grp:nnn{
+\seq_new:N\g_ocgbase_rbtn_groups_seq
+\cs_new_nopar:Nn\ocgbase_add_ocg_to_radiobtn_grp:nn{
% #1: rbtn group name,
- % #2: OCG obj ref,
- % #3: visible in Layers Tab
- \seq_if_in:NxF\g_ocgbase_ocgorder_seq{#1}{
- \seq_gput_right:Nx\g_ocgbase_ocgorder_seq{#1}
- \seq_new:c{g_ocgbase_#1_rbtn_order_seq}
- \seq_new:c{g_ocgbase_#1_rbtn_groups_seq}
+ % #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:cxTF{g_ocgbase_#1_rbtn_order_seq}{#2}{
- \bool_if:nT{
- \str_if_eq_x_p:nn{#3}{0} ||
- \str_if_eq_x_p:nn{#3}{false}
- }{
- \ocgbase_seq_gremove_all:cx{g_ocgbase_#1_rbtn_order_seq}{#2}
- }
- }{
- \bool_if:nF{
- \str_if_eq_x_p:nn{#3}{0} ||
- \str_if_eq_x_p:nn{#3}{false}
- }{
- \seq_gput_right:cx{g_ocgbase_#1_rbtn_order_seq}{#2}
- }
+ \seq_if_in:cxF{g_ocgbase_rbtn_group_#1_seq}{#2}{
+ \seq_gput_right:cx{g_ocgbase_rbtn_group_#1_seq}{#2}
}
- \seq_gput_right:cx{g_ocgbase_#1_rbtn_groups_seq}{#2}
}
% OC-marked content
@@ -297,34 +321,32 @@
\cs_new_nopar:Nn\ocgbase_oc_emc:{\pbs_pdfemc:}
%stack of PDF obj references of currently open OCGs
-\seq_new:N\g_ocgbase_ocgstack_seq
+\seq_new:N\g_ocgbase_open_stack_seq
%push OCG to stack
-\cs_new_nopar:Nn\ocgbase_ocgstack_push:n{
- \seq_gpush:Nx\g_ocgbase_ocgstack_seq{#1}}
+\cs_new_nopar:Nn\ocgbase_open_stack_push:n{
+ \seq_gpush:Nx\g_ocgbase_open_stack_seq{#1}}
%pop OCG from stack into tl
-\cs_new_nopar:Nn\ocgbase_ocgstack_pop:N{\seq_gpop:NN\g_ocgbase_ocgstack_seq#1}
-%get top OCG on stack, without removing it
-\cs_new_nopar:Nn\ocgbase_ocgstack_top:{
- \seq_item:Nn\g_ocgbase_ocgstack_seq{\c_one}}
+\cs_new_nopar:Nn\ocgbase_open_stack_pop:N{
+ \seq_gpop:NN\g_ocgbase_open_stack_seq#1}
%command that inserts /OC <<OCMD with currently open OCGs>> entry;
%for use within annotation/xobject dicts
\cs_new_nopar:Nn\ocgbase_insert_oc:{
- \seq_if_empty:NF\g_ocgbase_ocgstack_seq{
- /OC~<</Type/OCMD/OCGs~[\seq_use:Nn\g_ocgbase_ocgstack_seq{~}]/P/AllOn>>
+ \seq_if_empty:NF\g_ocgbase_open_stack_seq{
+ /OC~<</Type/OCMD/OCGs~[\seq_use:Nn\g_ocgbase_open_stack_seq{~}]/P/AllOn>>
}
}
%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@add@to@order@list\ocgbase_add_to_order_list:n
+\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:nnn
+\cs_gset_eq:NN\ocgbase@add@ocg@to@radiobtn@grp\ocgbase_add_ocg_to_radiobtn_grp:nn
\cs_gset_eq:NN\ocgbase@oc@bdc\ocgbase_oc_bdc:n
\cs_gset_eq:NN\ocgbase@oc@emc\ocgbase_oc_emc:
\cs_gset_eq:NN\ocgbase@insert@oc\ocgbase_insert_oc:
-\cs_gset_eq:NN\ocgbase@ocgstack@top\ocgbase_ocgstack_top:
-\cs_gset_eq:NN\ocgbase@ocgstack@pop\ocgbase_ocgstack_pop:N
-\cs_gset_eq:NN\ocgbase@ocgstack@push\ocgbase_ocgstack_push:n
+\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