summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx')
-rw-r--r--Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx294
1 files changed, 294 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx
new file mode 100644
index 00000000000..35f622ca1c9
--- /dev/null
+++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx
@@ -0,0 +1,294 @@
+% \iffalse meta-comment
+%
+%% File: tagpdf-tree.dtx
+%
+% Copyright (C) 2019-2020 Ulrike Fischer
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% https://www.latex-project.org/lppl.txt
+%
+% This file is part of the "tagpdf bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+% https://github.com/u-fischer/tagpdf
+%
+% for those people who are interested.
+%
+% \fi
+%
+% \begin{macrocode}
+%<@@=tag>
+%<*tree>
+\ProvidesExplPackage {tagpdf-tree-code} {2021/02/23} {0.80}
+ {part of tagpdf - code related to writing trees and dictionaries to the pdf}
+
+%this does the actual finishing:
+%Is \AfterEndDocument the best places??
+\hook_gput_code:nnn{begindocument}{tagpdf}
+ {
+ \bool_if:NT \g_@@_active_tree_bool
+ {
+ \AfterEndDocument { \tag_finish_structure: }
+ }
+ }
+
+
+% the StructTreeRoot
+% we better get the object number in any case:
+% deprecated
+%\@@_pdfreserveobjnum:N \l_tmpa_tl
+%\tl_const:Nx \c_@@_tree_obj_structtreeroot_tl { \l_tmpa_tl }
+
+%new
+\pdf_object_new:nn { c_@@_struct_0_obj }{ dict }
+
+ %need to think about the best place ...
+\hook_gput_code:nnn{begindocument}{tagpdf}
+ {
+ \bool_if:NT \g_@@_active_struct_bool
+ {
+ \pdfmanagement_add:nnx
+ { Catalog }
+ { StructTreeRoot }
+ { \pdf_object_ref:n { c_@@_struct_0_obj } }
+ }
+ }
+\cs_new_protected:Nn \@@_tree_write_structtreeroot:
+ {
+ \@@_struct_write_obj:n { 0 }
+ }
+
+\cs_new_protected:Nn \@@_tree_write_structelements:
+ {
+ \int_step_inline:nnnn {1}{1}{\c@g_@@_struct_abs_int}
+ {
+ %\prop_show:c {g_@@_struct_##1_prop}
+ \@@_struct_write_obj:n { ##1 } %write the object
+ }
+ }
+
+
+%the ParentTree
+% deprecated
+%\@@_pdfreserveobjnum:N \l_tmpa_tl
+%\tl_const:Nx \c_@@_tree_obj_parenttree_tl { \l_tmpa_tl }
+
+%new
+\pdf_object_new:nn { c_@@_tree_parenttree_obj }{ dict }
+
+% 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_@@_parenttree_obj_int }
+\hook_gput_code:nnn{begindocument}{tagpdf}
+ {
+ \int_gset:Nn
+ \c@g_@@_parenttree_obj_int
+ { \@@_ref_value_lastpage:nn{abspage}{100} }
+ }
+
+% we need to record the obj references:
+
+\tl_new:N \g_@@_parenttree_objr_tl
+
+\cs_new_protected:Nn \@@_parenttree_add_objr:nn %#1 Structparent number, #2 objref
+ {
+ \tl_gput_right:Nx \g_@@_parenttree_objr_tl
+ {
+ #1 \c_space_tl #2 ^^J
+ }
+ }
+
+\tl_new:N \l_@@_parenttree_content_tl
+
+\cs_new_protected:Nn \@@_tree_fill_parenttree:
+ {
+ \int_step_inline:nnnn{1}{1}{\@@_ref_value_lastpage:nn{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}{\@@_ref_value_lastpage:nn{tagmcabs}{-1}}
+ {
+ %mcid####1
+ \int_compare:nT%F
+ {\@@_ref_value:enn{mcid-####1}{tagabspage}{-1}=##1} %mcid is on current page
+ {% yes\par
+ \prop_put:Nxx
+ \l_tmpa_prop
+ {\@@_ref_value:enn{mcid-####1}{tagmcid}{-1}}
+ {\prop_item:Nn \g_@@_mc_parenttree_prop {####1}}
+ }
+ }
+ %\prop_show:N \l_tmpa_prop
+ \tl_put_right:Nx\l_@@_parenttree_content_tl
+ {
+ \int_eval:n {##1-1}\c_space_tl
+ [\c_space_tl %]
+ }
+ \int_step_inline:nnnn
+ {0}
+ {1}
+ { \prop_map_function:NN \l_tmpa_prop\@@_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_@@_parenttree_content_tl
+ {
+ \prop_item:cn { g_@@_struct_\l_tmpb_tl _prop } {objref}
+ \c_space_tl
+ }
+ %\tl_show:N \l_@@_parenttree_content_tl
+ }
+ {
+ \msg_warning:nn { tag } {tree-mcid-index-wrong}
+ }
+ }
+ \tl_put_right:Nn
+ \l_@@_parenttree_content_tl
+ {%[
+ ]^^J
+ }
+ }
+ }
+
+%lua mode must/can do it differently
+\cs_new_protected:Nn \@@_tree_lua_fill_parenttree:
+ {
+ \tl_set:Nn \l_@@_parenttree_content_tl
+ {
+ \directlua
+ {
+ ltx.@@.func.output_parenttree
+ (
+ \int_use:N\g_shipout_readonly_int
+ )
+ }
+ }
+ }
+
+
+
+\cs_new_protected:Nn \@@_tree_write_parenttree:
+ {
+ \bool_if:NTF \g_@@_mode_lua_bool
+ {
+ \@@_tree_lua_fill_parenttree:
+ }
+ {
+ \@@_tree_fill_parenttree:
+ }
+ \tl_put_right:NV \l_@@_parenttree_content_tl\g_@@_parenttree_objr_tl
+ \pdf_object_write:nx { c_@@_tree_parenttree_obj }
+ {
+ /Nums\c_space_tl [\l_@@_parenttree_content_tl]
+ }
+ }
+
+%the Rolemap tree
+%deprecated
+%\@@_pdfreserveobjnum:N \l_tmpa_tl
+%\tl_const:Nx \c_@@_tree_obj_rolemap_tl { \l_tmpa_tl }
+
+%new
+\pdf_object_new:nn { c_@@_tree_rolemap_obj }{ dict }
+
+\tl_new:N \l_@@_rolemap_content_tl
+
+\cs_new_protected:Nn \@@_tree_fill_rolemap:
+ {
+ \prop_map_inline:Nn \g_@@_role_rolemap_prop
+ {
+ \tl_put_right:Nx \l_@@_rolemap_content_tl
+ {
+ /##1\c_space_tl/##2^^J
+ }
+ }
+ }
+
+\cs_new_protected:Nn \@@_tree_write_rolemap:
+ {
+ \@@_tree_fill_rolemap:
+ \pdf_object_write:nx { c_@@_tree_rolemap_obj }
+ {
+ \l_@@_rolemap_content_tl
+ }
+ }
+
+%classmap, should only be written, if values has been used
+
+\cs_new_protected:Nn \@@_tree_write_classmap:
+ {
+ \tl_gclear:N \g_@@_attr_class_content_tl
+ \seq_gremove_duplicates:N \g_@@_attr_class_used_seq
+ \seq_set_map:NNn \l_tmpa_seq \g_@@_attr_class_used_seq
+ {
+ /##1\c_space_tl
+ <<
+ \prop_item:Nn
+ \g_@@_attr_entries_prop
+ {##1}
+ >>
+ }
+ \tl_gset:Nx \g_@@_attr_class_content_tl
+ {
+ \seq_use:Nn
+ \l_tmpa_seq
+ { \iow_newline: }
+ }
+ \tl_if_empty:NF
+ \g_@@_attr_class_content_tl
+ {
+ \pdf_object_new:nn { c_@@_tree_classmap_obj }{ dict }
+ % \@@_pdfreserveobjnum:N \l_tmpa_tl
+ % \tl_const:Nx \c_@@_tree_obj_classmap_tl { \l_tmpa_tl }
+ \pdf_object_write:nx
+ { c_@@_tree_classmap_obj }
+ { \g_@@_attr_class_content_tl }
+ \@@_prop_gput:cnx
+ { g_@@_struct_0_prop }
+ { ClassMap }
+ { \pdf_object_ref:n { c_@@_tree_classmap_obj } }
+ }
+ }
+
+
+\cs_new_protected:Nn \tag_finish_structure:
+ {
+ \@@_tree_write_parenttree:
+ \@@_tree_write_rolemap:
+ \@@_tree_write_classmap:
+ \@@_tree_write_structelements: %this is rather slow!!
+ \@@_tree_write_structtreeroot:
+ }
+
+%deprecated
+\cs_set_eq:NN \uftag_finish_structure: \tag_finish_structure:
+
+%StructParents !!! we need a better hook for \g__pdf_BACKEND_thispage_shipout_tl!!
+% No actually
+\hook_gput_code:nnn{begindocument}{tagpdf}
+ {
+ \bool_if:NT\g_@@_active_tree_bool
+ {
+ \hook_gput_code:nnn{shipout/before} { tagpdf/structparents }
+ {
+ \pdfmanagement_add:nnx
+ { Page }
+ {StructParents}
+ {\int_eval:n { \g_shipout_readonly_int}}
+ }
+ }
+ }
+
+%</tree>
+% \end{macrocode}