From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Mon, 2 Sep 2019 13:46:59 +0900
Subject: Initial commit

---
 macros/latex/contrib/tagpdf/tagpdf-tree-code.sty | 210 +++++++++++++++++++++++
 1 file changed, 210 insertions(+)
 create mode 100644 macros/latex/contrib/tagpdf/tagpdf-tree-code.sty

(limited to 'macros/latex/contrib/tagpdf/tagpdf-tree-code.sty')

diff --git a/macros/latex/contrib/tagpdf/tagpdf-tree-code.sty b/macros/latex/contrib/tagpdf/tagpdf-tree-code.sty
new file mode 100644
index 0000000000..af8ec11aa9
--- /dev/null
+++ b/macros/latex/contrib/tagpdf/tagpdf-tree-code.sty
@@ -0,0 +1,210 @@
+\ProvidesExplPackage {tagpdf-tree-code} {2019/07/02} {0.61}
+ {part of tagpdf - code related to writing trees and dictionaries to the pdf}
+
+%this does the actual finishing:
+\AtBeginDocument
+ {
+  \bool_if:NT \g_uftag_active_tree_bool
+   {
+    \AfterEndDocument { \uftag_finish_structure: }
+   }
+ }
+
+
+% the StructTreeRoot
+% we better get the object number in any case:
+\__uftag_pdfreserveobjnum:N \l_tmpa_tl
+\tl_const:Nx \c_uftag_tree_obj_structtreeroot_tl { \l_tmpa_tl }
+
+
+\cs_new:Nn \__uftag_tree_write_structtreeroot:
+ {
+  \__uftag_pdfcatalog:n { /StructTreeRoot~\c_uftag_tree_obj_structtreeroot_tl\c_space_tl0~R }
+  \__uftag_struct_write_obj:n { 0 }
+ }
+
+\cs_new:Nn \__uftag_tree_write_structelements:
+ {
+  \int_step_inline:nnnn {1}{1}{\c@g__uftag_struct_abs_int}
+   {
+     %\prop_show:c {g__uftag_struct_##1_prop}
+     \__uftag_struct_write_obj:n { ##1 } %write the object
+   }
+ }
+
+
+%the ParentTree
+\__uftag_pdfreserveobjnum:N \l_tmpa_tl
+\tl_const:Nx \c__uftag_tree_obj_parenttree_tl    { \l_tmpa_tl }
+
+% we have two sets of entries in the parent tree:
+% page streams and real objects.
+% The numbers must be distinct and ordered
+% So we rely on abspage and put the real objects at the end
+% I use a counter to have a chance to get the correct number
+% if code is process twice.
+\newcounter  { g__uftag_parenttree_obj_int }
+\AtBeginDocument
+ { \int_gset:Nn \c@g__uftag_parenttree_obj_int
+   { \zref@extractdefault{LastPage}{abspage}{100}  }
+ }
+
+% we need to record the obj references:
+
+\tl_new:N \g__uftag_parenttree_objr_tl
+
+\cs_new:Nn \__uftag_parenttree_add_objr:nn %#1 Structparent number, #2 obj number
+{
+ \tl_gput_right:Nx \g__uftag_parenttree_objr_tl
+  {
+   #1 \c_space_tl #2\c_space_tl 0 \c_space_tl R\c_space_tl ^^J
+  }
+}
+
+\tl_new:N \l__uftag_parenttree_content_tl
+
+\cs_new:Nn \__uftag_tree_fill_parenttree:
+ {
+  \int_step_inline:nnnn{1}{1}{\zref@extractdefault{LastPage}{abspage}{-1}} %not quite clear if labels are needed. See lua code
+  { %page ##1\par
+   \prop_clear:N \l_tmpa_prop
+   \int_step_inline:nnnn{1}{1}{\zref@extractdefault{LastPage}{tagmcabs}{-1}}
+   {
+    %mcid####1
+    \int_compare:nT%F
+     {\zref@extractdefault{mcid-####1}{tagabspage}{-1}=##1} %mcid is on current page
+     {% yes\par
+      \prop_put:Nxx \l_tmpa_prop
+      {\zref@extractdefault{mcid-####1}{tagmcid}{-1}}
+      {\prop_item:Nn \g__uftag_mc_parenttree_prop {####1}}
+     }
+   }
+   %\prop_show:N \l_tmpa_prop
+   \tl_put_right:Nx\l__uftag_parenttree_content_tl
+      {\int_eval:n {##1-1}\c_space_tl[\c_space_tl} %%brackt
+   \int_step_inline:nnnn {0}{1}{ \prop_map_function:NN \l_tmpa_prop\__uftag_prop_count:nn -1 }
+    {
+     \prop_get:NnNTF \l_tmpa_prop {####1} \l_tmpb_tl
+     {% page#1:mcid##1:\l_tmpb_tl :content
+       \tl_put_right:Nx \l__uftag_parenttree_content_tl
+        {
+         \prop_item:cn { g__uftag_struct_\l_tmpb_tl _prop } {objnum}~0~R~
+        }
+     }
+     {\msg_warning:nn {uftag} {tree-mcid-index-wrong} }
+    }
+   \tl_put_right:Nn \l__uftag_parenttree_content_tl {]^^J} %
+  }
+ }
+
+%lua mode must/can do it differently
+\cs_new:Nn \__uftag_tree_lua_fill_parenttree:
+ {
+  \tl_set:Nn \l__uftag_parenttree_content_tl
+   {
+    \directlua{uftag.func.output_parenttree(\int_use:N\g__uftag_abspage_int)}
+   }
+ }
+
+
+
+\cs_new:Nn \__uftag_tree_write_parenttree:
+ {
+  \bool_if:NTF \g__uftag_mode_lua_bool
+   {
+    \__uftag_tree_lua_fill_parenttree:
+   }
+   {
+    \__uftag_tree_fill_parenttree:
+   }
+  \tl_put_right:NV \l__uftag_parenttree_content_tl\g__uftag_parenttree_objr_tl
+  \__uftag_pdfuseobjnum:xx  { \c__uftag_tree_obj_parenttree_tl }
+   {
+    <<\c_space_tl/Nums\c_space_tl [\l__uftag_parenttree_content_tl] \c_space_tl >>
+   }
+ }
+
+%the Rolemap tree
+\__uftag_pdfreserveobjnum:N \l_tmpa_tl
+\tl_const:Nx \c__uftag_tree_obj_rolemap_tl { \l_tmpa_tl }
+\tl_new:N \l__uftag_rolemap_content_tl
+
+\cs_new:Nn \__uftag_tree_fill_rolemap:
+ {
+  \prop_map_inline:Nn \g__uftag_role_rolemap_prop
+   {
+    \tl_put_right:Nx \l__uftag_rolemap_content_tl
+     {
+      /##1\c_space_tl/##2^^J
+     }
+   }
+ }
+
+\cs_new:Nn \__uftag_tree_write_rolemap:
+ {
+  \__uftag_tree_fill_rolemap:
+  \__uftag_pdfuseobjnum:xx  { \c__uftag_tree_obj_rolemap_tl }
+   {
+    <<\l__uftag_rolemap_content_tl >>
+   }
+ }
+
+%classmap, should only be written, if values has been used
+
+\cs_new_protected:Nn \__uftag_tree_class_write_map:
+ {
+  \tl_gclear:N \g__uftag_attr_class_content_tl
+  \seq_gremove_duplicates:N \g__uftag_attr_class_used_seq
+  \seq_set_map:NNn \l_tmpa_seq \g__uftag_attr_class_used_seq
+   {
+     /##1\c_space_tl
+     \prop_item:Nn \g__uftag_attr_entries_prop
+       {##1}
+   }
+  \tl_gset:Nx \g__uftag_attr_class_content_tl
+   {
+    \seq_use:Nn \l_tmpa_seq
+     { \iow_newline: }
+   }
+  \tl_if_empty:NF \g__uftag_attr_class_content_tl
+  {
+   \__uftag_pdfreserveobjnum:N \l_tmpa_tl
+   \tl_const:Nx \c__uftag_tree_obj_classmap_tl { \l_tmpa_tl }
+   \__uftag_pdfuseobjnum:Nx \c__uftag_tree_obj_classmap_tl
+   { <<\g__uftag_attr_class_content_tl>> }
+
+   \__uftag_prop_gput:cnx
+    { g__uftag_struct_0_prop }
+    { ClassMap }
+    { \c__uftag_tree_obj_classmap_tl\c_space_tl0\c_space_tl R  }
+  }
+ }
+
+
+\cs_new:Nn \uftag_finish_structure:
+ {
+  \__uftag_pdfcatalog:n {^^J/MarkInfo\c_space_tl<</Marked\c_space_tl true>> }
+  \__uftag_tree_write_parenttree:
+  \__uftag_tree_write_rolemap:
+  \__uftag_tree_class_write_map:
+  \__uftag_tree_write_structelements:
+  \__uftag_tree_write_structtreeroot:
+ }
+
+
+%StructParents + tabs order. Tabs order should be probably be changeable by page.
+
+\cs_new:Nn \__uftag_tree_write_pageattr:
+ {
+  \__uftag_get_pdfpageattr:N \l_tmpa_tl
+  \regex_replace_once:nnN {/StructParents\s*\d+} {}\l_tmpa_tl
+  \regex_replace_once:nnN {/Tabs\s*/[SCR]} {}\l_tmpa_tl
+  \__uftag_gset_pdfpageattr:x
+   {
+    \l_tmpa_tl / StructParents \c_space_tl
+    \int_eval:n { \g__uftag_abspage_int }
+    \l__uftag_tree_tabs_order_tl
+   }
+ }
+
+\endinput
-- 
cgit v1.2.3

