diff options
author | Karl Berry <karl@freefriends.org> | 2021-06-30 21:14:14 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-06-30 21:14:14 +0000 |
commit | c604c653358384d71cfbdad75147fe6b3ef448d3 (patch) | |
tree | aaa2eb4dac429b5bb9bdde1d867e88d75612e65d /Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty | |
parent | f52cb629a5dd055df1ae60054f89cc718a5ce58e (diff) |
tagpdf (30jun21)
git-svn-id: svn://tug.org/texlive/trunk@59769 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty')
-rw-r--r-- | Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty | 2235 |
1 files changed, 2128 insertions, 107 deletions
diff --git a/Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty b/Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty index 75825724cfd..4b0623e244a 100644 --- a/Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty +++ b/Master/texmf-dist/tex/latex/tagpdf/tagpdf.sty @@ -5,8 +5,16 @@ %% The original source files were: %% %% tagpdf.dtx (with options: `package') +%% tagpdf-checks.dtx (with options: `package') +%% tagpdf-user.dtx (with options: `package') +%% tagpdf-mc-shared.dtx (with options: `shared') +%% tagpdf.dtx (with options: `mcloading') +%% tagpdf-tree.dtx (with options: `package') +%% tagpdf-roles.dtx (with options: `package') +%% tagpdf-struct.dtx (with options: `package') +%% tagpdf-space.dtx (with options: `package') %% -%% Copyright (C) 2019 Ulrike Fischer +%% Copyright (C) 2019-2021 Ulrike Fischer %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of @@ -19,7 +27,7 @@ %% and all files in that bundle must be distributed together. %% %% File: tagpdf.dtx -\ProvidesExplPackage {tagpdf} {2021-06-14} {0.82} +\ProvidesExplPackage {tagpdf} {2021-06-29} {0.9} { A package to experiment with pdf tagging } \bool_if:nF @@ -41,29 +49,16 @@ before~\string\documentclass } } - - \prop_if_exist:NT \g_msg_module_name_prop { \prop_gput:Nnn \g_msg_module_name_prop { tag }{ tagpdf } } - -\cs_set_eq:NN \__tag_tex_global:D \tex_global:D - -%%% package options \bool_new:N\g__tag_mode_lua_bool - \DeclareOption {luamode} { \sys_if_engine_luatex:T { \bool_gset_true:N \g__tag_mode_lua_bool } } \DeclareOption {genericmode}{ \bool_gset_false:N\g__tag_mode_lua_bool } \ExecuteOptions{luamode} \ProcessOptions - -%%% some packages \RequirePackage{l3ref-tmp} - %================ - % temporary code - % =============== - % faking the LastPage label: \cs_new_protected:Npn \__tag_lastpagelabel: { \legacy_if:nT { @filesw } @@ -82,8 +77,6 @@ \AddToHook{enddocument/afterlastpage} {\__tag_lastpagelabel:} - - % a command to override the general default. See issue in ref \cs_if_exist:NF \ref_value:nnn { \cs_new:Npn \ref_value:nnn #1#2#3 @@ -97,66 +90,106 @@ \tl_if_exist:cTF { g__ref_label_ #1 _ #2 _tl } { \tl_use:c { g__ref_label_ #1 _ #2 _tl } } { - % test if attribute exist at all? #3 } } } - %============= - % attributes - %============= -\ref_attribute_gset:nnnn {tagstruct} {0}{now} { \int_use:N \c@g__tag_struct_abs_int } -\ref_attribute_gset:nnnn {tagstructobj} {}{now} - { - \exp_args:Ne - \pdf_object_if_exist:nT {__tag/struct/\int_use:N \c@g__tag_struct_abs_int} - { - \pdf_object_ref:e{__tag/struct/\int_use:N \c@g__tag_struct_abs_int} - } - } - % replace by abspage?? -\ref_attribute_gset:nnnn {tagabspage}{0}{shipout}{ \int_use:N \g_shipout_readonly_int } -\ref_attribute_gset:nnnn {tagmcabs } {0}{now} { \int_use:N \c@g__tag_MCID_abs_int } -\ref_attribute_gset:nnnn {tagmcid } {0}{now} { \int_use:N \g__tag_MCID_tmp_bypage_int } -\clist_const:Nn \c__tag_refmc_clist {tagabspage,tagmcabs,tagmcid} %mc is new!! +\tl_new:N \l__tag_tmpa_tl +\str_new:N \l__tag_tmpa_str +\prop_new:N \l__tag_tmpa_prop +\seq_new:N \l__tag_tmpa_seq +\seq_new:N \l__tag_tmpb_seq +\clist_new:N \l__tag_tmpa_clist +\int_new:N \l__tag_tmpa_int +\clist_const:Nn \c__tag_refmc_clist {tagabspage,tagmcabs,tagmcid} \clist_const:Nn \c__tag_refstruct_clist {tagstruct,tagstructobj} +\int_new:N \l__tag_loglevel_int +\bool_new:N \g__tag_active_space_bool +\bool_new:N \g__tag_active_mc_bool +\bool_new:N \g__tag_active_tree_bool +\bool_new:N \g__tag_active_struct_bool + +\bool_new:N \l__tag_active_mc_bool +\bool_set_true:N \l__tag_active_mc_bool +\bool_new:N \l__tag_active_struct_bool +\bool_set_true:N \l__tag_active_struct_bool +\bool_new:N \g__tag_tagunmarked_bool +\prg_generate_conditional_variant:Nnn \pdf_object_if_exist:n {e}{T,F} +\cs_generate_variant:Nn \pdf_object_ref:n {e} +\cs_generate_variant:Nn \pdfannot_dict_put:nnn {nnx} +\cs_generate_variant:Nn \pdffile_embed_stream:nnn {nxx,oxx} +\cs_generate_variant:Nn \prop_gput:Nnn {Nxx} +\cs_generate_variant:Nn \prop_put:Nnn {Nxx} \cs_generate_variant:Nn \ref_label:nn { nv } +\cs_generate_variant:Nn \seq_set_split:Nnn{Nne} +\cs_generate_variant:Nn \str_set_convert:Nnnn {Nonn, Noon, Nnon } + +\ref_attribute_gset:nnnn { tagstruct } {0} { now } + { \int_use:N \c@g__tag_struct_abs_int } +\ref_attribute_gset:nnnn { tagstructobj } {} { now } + { + \pdf_object_if_exist:eT {__tag/struct/\int_use:N \c@g__tag_struct_abs_int} + { + \pdf_object_ref:e{__tag/struct/\int_use:N \c@g__tag_struct_abs_int} + } + } +\ref_attribute_gset:nnnn { tagabspage } {0} { shipout } + { \int_use:N \g_shipout_readonly_int } +\ref_attribute_gset:nnnn { tagmcabs } {0} { now } + { \int_use:N \c@g__tag_MCID_abs_int } +\ref_attribute_gset:nnnn {tagmcid } {0} { now } + { \int_use:N \g__tag_MCID_tmp_bypage_int } \cs_new_protected:Npn \__tag_ref_label:nn #1 #2 %#1 label, #2 name of list mc or struct { \@bsphack \ref_label:nv {#1}{c__tag_ref#2_clist} \@esphack } +\cs_generate_variant:Nn \__tag_ref_label:nn {en} \cs_new:Npn \__tag_ref_value:nnn #1 #2 #3 %#1 label, #2 attribute, #3 default { \ref_value:nnn {#1}{#2}{#3} } +\cs_generate_variant:Nn \__tag_ref_value:nnn {enn} \cs_new:Npn \__tag_ref_value_lastpage:nn #1 #2 { \ref_value:nnn {__tag_LastPage}{#1}{#2} } -\cs_generate_variant:Nn \__tag_ref_label:nn {en} -\cs_generate_variant:Nn \__tag_ref_value:nnn {enn} - -\RequirePackage{etoolbox} +\cs_set_eq:NN \__tag_prop_new:N \prop_new:N +\cs_set_eq:NN \__tag_seq_new:N \seq_new:N +\cs_set_eq:NN \__tag_prop_gput:Nnn \prop_gput:Nnn +\cs_set_eq:NN \__tag_seq_gput_right:Nn \seq_gput_right:Nn +\cs_set_eq:NN \__tag_seq_item:cn \seq_item:cn +\cs_set_eq:NN \__tag_prop_item:cn \prop_item:cn +\cs_set_eq:NN \__tag_seq_show:N \seq_show:N +\cs_set_eq:NN \__tag_prop_show:N \prop_show:N -\cs_generate_variant:Nn \str_set_convert:Nnnn {Nonn, Noon, Nnon } +\cs_generate_variant:Nn \__tag_prop_gput:Nnn { Nxn , Nxx, Nnx , cnn, cxn, cnx, cno} +\cs_generate_variant:Nn \__tag_seq_gput_right:Nn { Nx , No, cn, cx } +\cs_generate_variant:Nn \__tag_prop_new:N { c } +\cs_generate_variant:Nn \__tag_seq_new:N { c } +\cs_generate_variant:Nn \__tag_seq_show:N { c } +\cs_generate_variant:Nn \__tag_prop_show:N { c } -%%% tagpdfsetup, -%%% TODO: checks need to be improved -\int_new:N \l__tag_loglevel_int -\tl_new:N \l__tag_tree_tabs_order_tl +\cs_new_protected:Npn \tag_stop_group_begin: + { + \group_begin: + \bool_set_false:N \l__tag_active_struct_bool + \bool_set_false:N \l__tag_active_mc_bool + } +\cs_set_eq:NN \tag_stop_group_end: \group_end: \keys_define:nn { __tag / setup } { + activate-space .bool_gset:N = \g__tag_active_space_bool, activate-mc .bool_gset:N = \g__tag_active_mc_bool, activate-tree .bool_gset:N = \g__tag_active_tree_bool, activate-struct .bool_gset:N = \g__tag_active_struct_bool, - activate-all .meta:n ={activate-mc,activate-tree,activate-struct}, - check-tags .bool_gset:N = \g__tag_check_tags_bool, - check-tags .initial:n = true, + activate-all .meta:n = + {activate-mc,activate-tree,activate-struct}, + % \end{macrocode} log .choice:, log / none .code:n = {\int_set:Nn \l__tag_loglevel_int { 0 }}, log / v .code:n = {\int_set:Nn \l__tag_loglevel_int { 1 }}, @@ -166,109 +199,2097 @@ tagunmarked .bool_gset:N = \g__tag_tagunmarked_bool, tagunmarked .initial:n = true, tabsorder .choice:, - tabsorder / row .code:n = %{\tl_set:Nn \l__tag_tree_tabs_order_tl {/Tabs/R}}, + tabsorder / row .code:n = \pdfmanagement_add:nnn { Page } {Tabs}{/R}, - tabsorder / column .code:n = %{\tl_set:Nn \l__tag_tree_tabs_order_tl {/Tabs/C}}, + tabsorder / column .code:n = \pdfmanagement_add:nnn { Page } {Tabs}{/C}, - tabsorder / structure .code:n = %{\tl_set:Nn \l__tag_tree_tabs_order_tl {/Tabs/S}}, + tabsorder / structure .code:n = \pdfmanagement_add:nnn { Page } {Tabs}{/S}, - tabsorder / none .code:n = %{\tl_set:Nn \l__tag_tree_tabs_order_tl {}}, + tabsorder / none .code:n = \pdfmanagement_remove:nn {Page} {Tabs}, tabsorder .initial:n = structure, - uncompress .code:n = {\pdf_uncompress: }, - global-mc .code:n = + uncompress .code:n = { \pdf_uncompress: }, + } +\sys_if_engine_luatex:T + { + \file_input:n {tagpdf-luatex.def} + } +%% File: tagpdf-checks.dtx + +\msg_new:nnn { tag } {mc-nested} { nested~marked~content~found~-~mcid~#1 } +\msg_new:nnn { tag } {mc-tag-missing} { required~tag~missing~-~mcid~#1 } +\msg_new:nnn { tag } {mc-label-unknown} + { label~#1~unknown~or~has~been~already~used.\\ + Either~rerun~or~remove~one~of~the~uses. } +\msg_new:nnn { tag } {mc-used-twice} { mc~#1~has~been~already~used } +\msg_new:nnn { tag } {mc-not-open} { there~is~no~mc~to~end~at~#1 } +\msg_new:nnn { tag } {mc-pushed} { #1~has~been~pushed~to~the~mc~stack} +\msg_new:nnn { tag } {mc-popped} { #1~has~been~removed~from~the~mc~stack } +\msg_new:nnn { tag } {mc-current} + { current~MC:~ + \bool_if:NTF\g__tag_in_mc_bool + {abscnt=\__tag_get_mc_abs_cnt:,~tag=\g__tag_mc_key_tag_tl} + {no~MC~open,~current~abscnt=\__tag_get_mc_abs_cnt:"} + } +\msg_new:nnn { tag } {struct-no-objnum} { objnum~missing~for~structure~#1 } +\msg_new:nnn { tag } + {struct-faulty-nesting} + { there~is~no~open~structure~on~the~stack } +\msg_new:nnn { tag } {struct-missing-tag} { a~structure~must~have~a~tag! } +\msg_new:nnn { tag } {struct-used-twice} + { structure~with~label~#1~has~already~been~used} +\msg_new:nnn { tag } {struct-label-unknown} + { structure~with~label~#1~is~unknown~rerun} +\msg_new:nnn { tag } {struct-show-closing} + { closing~structure~#1~tagged~\prop_item:cn{g__tag_struct_#1_prop}{S} } +\msg_new:nnn { tag } {attr-unknown} { attribute~#1~is~unknown} +\msg_new:nnn { tag } {role-missing} { tag~#1~has~no~role~assigned } +\msg_new:nnn { tag } {role-unknown} { role~#1~is~not~known } +\msg_new:nnn { tag } {role-unknown-tag} { tag~#1~is~not~known } +\msg_new:nnn { tag } {role-tag} { mapping~tag~#1~to~role~#2 } +\msg_new:nnn { tag } {new-tag} { adding~new~tag~#1 } +\msg_new:nnn { tag } {tree-mcid-index-wrong} + {something~is~wrong~with~the~mcid--rerun} +\msg_new:nnn { tag } {sys-no-interwordspace} + {engine/output~mode~#1~doesn't~support~the~interword~spaces} +\cs_new:Npn \tag_get:n #1 { \use:c {__tag_get_data_#1: } } +\prg_new_conditional:Npnn \tag_if_active: { p , T , TF, F } + { + \bool_lazy_all:nTF + { + {\g__tag_active_struct_bool} + {\g__tag_active_mc_bool} + {\g__tag_active_tree_bool} + {\l__tag_active_struct_bool} + {\l__tag_active_mc_bool} + } + { + \prg_return_true: + } + { + \prg_return_false: + } + } +\prg_new_conditional:Npnn \__tag_check_if_active_mc: {T,F,TF} + { + \bool_lazy_and:nnTF { \g__tag_active_mc_bool } { \l__tag_active_mc_bool } + { + \prg_return_true: + } { - \cs_set_eq:NN\__tag_attribute_set:Nn \__tag_attribute_gset:Nn - \cs_set_eq:NN\__tag_attribute_unset:N\__tag_attribute_gunset:N + \prg_return_false: } } -\hook_gput_code:nnn{begindocument}{tagpdf} +\prg_new_conditional:Npnn \__tag_check_if_active_struct: {T,F,TF} { - \bool_if:NT \g__tag_active_struct_bool + \bool_lazy_and:nnTF { \g__tag_active_struct_bool } { \l__tag_active_struct_bool } { - \pdfmanagement_add:nnn { Catalog / MarkInfo } { Marked } { true } + \prg_return_true: } - \keys_define:nn { __tag / setup } + { + \prg_return_false: + } + } +\cs_new_protected:Npn \__tag_check_structure_has_tag:n #1 %#1 struct num + { + \prop_if_in:cnF { g__tag_struct_#1_prop } + {S} + { + \msg_error:nn { tag } {struct-missing-tag} + } + } +\cs_new_protected:Npn \__tag_check_structure_tag:N #1 + { + \prop_if_in:NoF \g__tag_role_tags_prop {#1} + { + \msg_warning:nnx { tag } {role-unknown-tag} {#1} + } + } +\cs_new_protected:Npn \__tag_check_info_closing_struct:n #1 %#1 struct num + { + \int_compare:nNnT {\l__tag_loglevel_int} > { 0 } + { + \msg_info:nnn { tag } {struct-show-closing} {#1} + } + } + +\cs_generate_variant:Nn \__tag_check_info_closing_struct:n {o,x} +\cs_new_protected:Npn \__tag_check_no_open_struct: + { + \msg_error:nn { tag } {struct-faulty-nesting} + } +\cs_new_protected:Npn \__tag_check_struct_used:n #1 %#1 label + { + \prop_get:cnNT + {g__tag_struct_\__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{unknown}_prop} + {P} + \l_tmpa_tl + { + \msg_warning:nnn { tag } {struct-used-twice} {#1} + } + } +\cs_new_protected:Npn \__tag_check_add_tag_role:nn #1 #2 %#1 tag, #2 role + { + \tl_if_empty:nTF {#2} + { + \msg_warning:nnn { tag } {role-missing} {#1} + } + { + \prop_get:NnNTF \g__tag_role_tags_prop {#2} \l_tmpa_tl + { + \int_compare:nNnT {\l__tag_loglevel_int} > { 0 } + { + \msg_info:nnnn { tag } {role-tag} {#1} {#2} + } + } + { + \msg_warning:nnn { tag } {role-unknown} {#2} + } + } + } +\cs_new_protected:Npn \__tag_check_mc_if_nested: + { + \__tag_mc_if_in:T + { + \msg_warning:nnx { tag } {mc-nested} { \__tag_get_mc_abs_cnt: } + } + } + +\cs_new_protected:Npn \__tag_check_mc_if_open: + { + \__tag_mc_if_in:F + { + \msg_warning:nnx { tag } {mc-not-open} { \__tag_get_mc_abs_cnt: } + } + } +\cs_new_protected:Npn \__tag_check_mc_pushed_popped:nn #1 #2 + { + \int_compare:nNnT + { \l__tag_loglevel_int } ={ 2 } + { \msg_info:nnx {tag}{mc-#1}{#2} } + \int_compare:nNnT + { \l__tag_loglevel_int } > { 2 } + { + \msg_info:nnx {tag}{mc-#1}{#2} + \seq_log:N \g__tag_mc_stack_seq + } + } +\cs_new_protected:Npn \__tag_check_mc_tag:N #1 %#1 is var with a tag name in it + { + \tl_if_empty:NT #1 + { + \msg_error:nnx { tag } {mc-tag-missing} { \__tag_get_mc_abs_cnt: } + } + \prop_if_in:NoF \g__tag_role_tags_NS_prop {#1} { - global-mc .code:n={} + \msg_warning:nnx { tag } {role-unknown-tag} {#1} } } +\cs_new_protected:Npn \__tag_check_init_mc_used: + { + \intarray_new:Nn \g__tag_check_mc_used_intarray { 65536 } + \cs_gset_eq:NN \__tag_check_init_mc_used: \prg_do_nothing: + } +\cs_new_protected:Npn \__tag_check_mc_used:n #1 %#1 mcid abscnt + { + \int_compare:nNnT {\l__tag_loglevel_int} > { 2 } + { + \__tag_check_init_mc_used: + \intarray_gset:Nnn \g__tag_check_mc_used_intarray + {#1} + { \intarray_item:Nn \g__tag_check_mc_used_intarray {#1} + 1 } + \int_compare:nNnT + { + \intarray_item:Nn \g__tag_check_mc_used_intarray {#1} + } + > + { 1 } + { + \msg_warning:nnn { tag } {mc-used-twice} {#1} + } + } + } +\cs_new_protected:Npn \__tag_check_show_MCID_by_page: + { + \tl_set:Nx \l__tag_tmpa_tl + { + \__tag_ref_value_lastpage:nn + {abspage} + {-1} + } + \int_step_inline:nnnn {1}{1} + { + \l__tag_tmpa_tl + } + { + \seq_clear:N \l_tmpa_seq + \int_step_inline:nnnn + {1} + {1} + { + \__tag_ref_value_lastpage:nn + {tagmcabs} + {-1} + } + { + \int_compare:nT + { + \__tag_ref_value:enn + {mcid-####1} + {tagabspage} + {-1} + = + ##1 + } + { + \seq_gput_right:Nx \l_tmpa_seq + { + Page##1-####1- + \__tag_ref_value:enn + {mcid-####1} + {tagmcid} + {-1} + } + } + } + \seq_show:N \l_tmpa_seq + } + } +%% File: tagpdf-user.dtx +\NewDocumentCommand \tagpdfsetup { m } + { + \keys_set:nn { __tag / setup } { #1 } + } +\NewDocumentCommand \tagmcbegin { m } + { + \tag_mc_begin:n {#1}%\ignorespaces + } -\cs_new:Nn \__tag_finish_page_hook: { } +\NewDocumentCommand \tagmcend { } + { + %\if_mode_horizontal: \unskip \fi: % + \tag_mc_end: + } +\NewDocumentCommand \tagmcuse { m } + { + \tag_mc_use:n {#1} + } -\hook_gput_code:nnn - { shipout/before } - { tagpdf/cnt } + +\NewDocumentCommand \tagmcifinTF { m m } { - \__tag_finish_page_hook: - %\int_gincr:N \g__tag_abspage_int + \tag_mc_if_in:TF { #1 } { #2 } + } +\NewDocumentCommand \tagstructbegin { m } + { + \tag_struct_begin:n {#1} } -\sys_if_engine_xetex:T - { %lets try with xelatex ... - %\PackageError { tagpdf } { xelatex~is~not~supported~-~aborting } {} - %\tex_endinput:D - \file_input:n {tagpdf-pdftex.def} +\NewDocumentCommand \tagstructend { } + { + \tag_struct_end: + } + +\NewDocumentCommand \tagstructuse { m } + { + \tag_struct_use:n {#1} + } +\cs_set_eq:NN\tagpdfifluatexTF \sys_if_engine_luatex:TF +\cs_set_eq:NN\tagpdfifluatexT \sys_if_engine_luatex:T +\cs_set_eq:NN\tagpdfifpdftexT \sys_if_engine_pdftex:T +\NewDocumentCommand\ShowTagging { m } + { + \keys_set:nn { __tag / show }{ #1} + + } +\keys_define:nn { __tag / show } + { + mc-data .code:n = + { + \sys_if_engine_luatex:T + { + \lua_now:e{ltx.__tag.trace.show_all_mc_data(#1,\__tag_get_mc_abs_cnt:,0)} + } + } + ,mc-data .default:n = 1 } +\keys_define:nn { __tag / show } + { mc-current .code:n = + { + \bool_if:NTF \g__tag_mode_lua_bool + { + \sys_if_engine_luatex:T + { + \int_compare:nNnTF + { -2147483647 } + = + { + \lua_now:e + { + tex.print + (tex.getattribute + (luatexbase.attributes.g__tag_mc_cnt_attr)) + } + } + { + \lua_now:e + { + ltx.__tag.trace.log + ( + "mc-current:~no~MC~open,~current~abscnt + =\__tag_get_mc_abs_cnt:" + ,0 + ) + texio.write_nl("") + } + } + { + \lua_now:e + { + ltx.__tag.trace.log + ( + "mc-current:~abscnt=\__tag_get_mc_abs_cnt:==" + .. + tex.getattribute(luatexbase.attributes.g__tag_mc_cnt_attr) + .. + "~=>tag=" + .. + tostring + (ltx.__tag.func.get_tag_from + (tex.getattribute + (luatexbase.attributes.g__tag_mc_type_attr))) + .. + "=" + .. + tex.getattribute + (luatexbase.attributes.g__tag_mc_type_attr) + ,0 + ) + texio.write_nl("") + } + } + } + } + { + \msg_note:nn{ tag }{ mc-current } + } + } + } +\keys_define:nn { __tag / show } + { + struct-stack .choice: + ,struct-stack / log .code:n = \seq_log:N \g__tag_struct_tag_stack_seq + ,struct-stack / show .code:n = \seq_show:N \g__tag_struct_tag_stack_seq + ,struct-stack .default:n = show + } +\cs_new_protected:Npn \__tag_add_document_structure:n #1 + { + \hook_gput_code:nnn{begindocument}{tagpdf}{\tagstructbegin{tag=#1}} + \hook_gput_code:nnn{tagpdf/finish/before}{tagpdf}{\tagstructend} + } +\keys_define:nn { __tag / setup} + { + activate .code:n = + { + \keys_set:nn { __tag / setup } + { activate-mc,activate-tree,activate-struct } + \__tag_add_document_structure:n {#1} + }, + activate .default:n = Document + } \sys_if_engine_luatex:T { - \file_input:n {tagpdf-luatex.def} + \NewDocumentCommand\pdffakespace { } + { + \__tag_fakespace: + } + } +\bool_new:N \l__tag_para_bool +\bool_new:N \l__tag_para_show_bool +\int_new:N \g__tag_para_int +\keys_define:nn { __tag / setup } + { + paratagging .bool_set:N = \l__tag_para_bool, + paratagging-show .bool_set:N = \l__tag_para_show_bool, } -\sys_if_engine_pdftex:T +\AddToHook{para/begin} { - \file_input:n {tagpdf-pdftex.def} + \int_gincr:N \g__tag_para_int + \bool_if:NT \l__tag_para_bool + { + \tag_struct_begin:n {tag=P} + \bool_if:NT \l__tag_para_show_bool + { \tag_mc_begin:n{artifact} + \llap{\color_select:n{red}\tiny\int_use:N\g__tag_para_int\ } + \tag_mc_end: + } + \tag_mc_begin:n {tag=P} + } + } +\AddToHook{para/end} + { + \bool_if:NT \l__tag_para_bool + { + \tag_mc_end: + \bool_if:NT \l__tag_para_show_bool + { \tag_mc_begin:n{artifact} + \rlap{\color_select:n{red}\tiny\ \int_use:N\g__tag_para_int} + \tag_mc_end: + } + \tag_struct_end: + } + } +\newcommand\tagpdfparaOn {\bool_set_true:N \l__tag_para_bool} +\newcommand\tagpdfparaOff{\bool_set_false:N \l__tag_para_bool} +\hook_gput_code:nnn + {pdfannot/link/URI/before} + {tagpdf} + { + \tag_mc_end_push: + \tag_struct_begin:n { tag=Link } + \tag_mc_begin:n { tag=Link } + \pdfannot_dict_put:nnx + { link/URI } + { StructParent } + { \tag_struct_parent_int: } } -\sys_if_output_dvi:T +\hook_gput_code:nnn + {pdfannot/link/URI/after} + {tagpdf} { - %\PackageError { tagpdf } { dvi~output~is~not~supported~-~aborting }{} - %\tex_endinput:D + \tag_struct_insert_annot:xx {\pdfannot_link_ref_last:}{\tag_struct_parent_int:} + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin_pop:n{} } -\cs_generate_variant:Nn \__tag_prop_gput:Nnn { Nxn , Nxx, Nnx , cnn, cxn, cnx, cno} -\cs_generate_variant:Nn \__tag_seq_gput_right:Nn { Nx , No, cn, cx } -\cs_generate_variant:Nn \__tag_prop_new:N { c } -\cs_generate_variant:Nn \__tag_seq_new:N { c } -\cs_generate_variant:Nn \__tag_seq_show:N { c } -\cs_generate_variant:Nn \__tag_prop_show:N { c } -\cs_generate_variant:Nn \prop_gput:Nnn {Nxx} -\cs_generate_variant:Nn \prop_put:Nnn {Nxx} +\hook_gput_code:nnn + {pdfannot/link/GoTo/before} + {tagpdf} + { + \tag_mc_end_push: + \tag_struct_begin:n{tag=Link} + \tag_mc_begin:n{tag=Link} + \pdfannot_dict_put:nnx + { link/GoTo } + { StructParent } + { \tag_struct_parent_int: } + } -\cs_generate_variant:Nn \pdffile_embed_stream:nnn {nxx,oxx} -\cs_generate_variant:Nn \pdf_object_ref:n {e} +\hook_gput_code:nnn + {pdfannot/link/GoTo/after} + {tagpdf} + { + \tag_struct_insert_annot:xx {\pdfannot_link_ref_last:}{\tag_struct_parent_int:} + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin_pop:n{} + + } + +\pdfannot_dict_put:nnn + { link/URI } + { Contents } + { (url) } + +\pdfannot_dict_put:nnn + { link/GoTo } + { Contents } + { (ref) } + +%% File: tagpdf-mc.dtx + +\newcounter { g__tag_MCID_abs_int } +\cs_new:Npn \__tag_get_mc_abs_cnt: { \int_use:N \c@g__tag_MCID_abs_int } +\int_new:N \g__tag_MCID_tmp_bypage_int +\__tag_prop_new:N \g__tag_mc_parenttree_prop +\seq_new:N \g__tag_mc_stack_seq +\tl_new:N \l__tag_mc_artifact_type_tl +\bool_new:N \l__tag_mc_key_stash_bool +\bool_new:N \l__tag_mc_artifact_bool +\tl_new:N \l__tag_mc_key_tag_tl +\tl_new:N \g__tag_mc_key_tag_tl +\tl_new:N \l__tag_mc_key_label_tl +\tl_new:N \l__tag_mc_key_properties_tl +\cs_new:Nn \__tag_mc_handle_mc_label:n + { + \__tag_ref_label:en{tagpdf-#1}{mc} + } +\cs_new_protected:Npn \__tag_mc_set_label_used:n #1 %#1 labelname + { + \tl_new:c { g__tag_mc_label_\tl_to_str:n{#1}_used_tl } + } +\cs_new_protected:Npn \tag_mc_use:n #1 %#1: label name + { + \__tag_check_if_active_struct:T + { + \tl_set:Nx \l__tag_tmpa_tl { \__tag_ref_value:nnn{tagpdf-#1}{tagmcabs}{} } + \tl_if_empty:NTF\l__tag_tmpa_tl + { + \msg_warning:nnn {tag} {mc-label-unknown} {#1} + } + { + \cs_if_free:cTF { g__tag_mc_label_\tl_to_str:n{#1}_used_tl } + { + \__tag_mc_handle_stash:x { \l__tag_tmpa_tl } + \__tag_mc_set_label_used:n {#1} + } + { + \msg_warning:nnn {tag}{mc-used-twice}{#1} + } + } + } + } +\cs_new_protected:Npn \tag_mc_artifact_group_begin:n #1 + { + \tag_mc_end_push: + \tag_mc_begin:n {artifact=#1} + \tag_stop_group_begin: + } + +\cs_new_protected:Npn \tag_mc_artifact_group_end: + { + \tag_stop_group_end: + \tag_mc_end: + \tag_mc_begin_pop:n{} + } +\cs_new_protected:Npn \tag_mc_end_push: + { + \__tag_check_if_active_mc:T + { + \__tag_mc_if_in:TF + { + \seq_gpush:Nx \g__tag_mc_stack_seq { \tag_get:n {mc_tag} } + \__tag_check_mc_pushed_popped:nn + { pushed } + { \tag_get:n {mc_tag} } + \tag_mc_end: + } + { + \seq_gpush:Nn \g__tag_mc_stack_seq {-1} + \__tag_check_mc_pushed_popped:nn { pushed }{-1} + } + } + } -\tl_new:N \g__tag_tmpa_tl -\tl_new:N \l__tag_tmpa_tl -\tl_new:N \l__tag_tmpb_tl -\tl_new:N \l__tag_tmpc_tl -\tl_new:N \l__tag_tmpd_tl -\tl_new:N \l__tag_tmpe_tl -\str_new:N \l__tag_tmpa_str - -\cs_new:Nn\__tag_prop_count:nn { + 1 } - -%% Loading the tagpdf sub packages -\RequirePackage { tagpdf-checks-code } -\RequirePackage { tagpdf-user } -\RequirePackage { tagpdf-tree-code } -\RequirePackage { tagpdf-roles-code } -\RequirePackage { tagpdf-attr-code } -\RequirePackage { tagpdf-mc-code-shared } +\cs_new_protected:Npn \tag_mc_begin_pop:n #1 + { + \__tag_check_if_active_mc:T + { + \seq_gpop:NNTF \g__tag_mc_stack_seq \l__tag_tmpa_tl + { + \tl_if_eq:NnTF \l__tag_tmpa_tl {-1} + { + \__tag_check_mc_pushed_popped:nn {popped}{-1} + } + { + \__tag_check_mc_pushed_popped:nn {popped}{\l__tag_tmpa_tl} + \tag_mc_begin:n {tag=\l__tag_tmpa_tl,#1} + } + } + { + \__tag_check_mc_pushed_popped:nn {popped}{empty~stack,~nothing} + } + } + } +\keys_define:nn { __tag / mc } + { + stash .bool_set:N = \l__tag_mc_key_stash_bool, + __artifact-bool .bool_set:N = \l__tag_mc_artifact_bool, + __artifact-type .choice:, + __artifact-type / pagination .code:n = + { + \tl_set:Nn \l__tag_mc_artifact_type_tl { Pagination } + }, + __artifact-type / layout .code:n = + { + \tl_set:Nn \l__tag_mc_artifact_type_tl { Layout } + }, + __artifact-type / page .code:n = + { + \tl_set:Nn \l__tag_mc_artifact_type_tl { Page } + }, + __artifact-type / background .code:n = + { + \tl_set:Nn \l__tag_mc_artifact_type_tl { Background } + }, + __artifact-type / notype .code:n = + { + \tl_set:Nn \l__tag_mc_artifact_type_tl {} + }, + __artifact-type / .code:n = + { + \tl_set:Nn \l__tag_mc_artifact_type_tl {} + }, + } +%% File: tagpdf.dtx \bool_if:NTF \g__tag_mode_lua_bool { \RequirePackage {tagpdf-mc-code-lua} } { - \RequirePackage { tagpdf-mc-code-generic } % + \RequirePackage {tagpdf-mc-code-generic} % + } +%% File: tagpdf-tree.dtx +\hook_gput_code:nnn{begindocument}{tagpdf} + { + \bool_if:NT \g__tag_active_tree_bool + { + \sys_if_output_pdf:TF + { + \AddToHook{enddocument/end} { \__tag_finish_structure: } + } + { + \AddToHook{shipout/lastpage} { \__tag_finish_structure: } + } + } + } +\pdf_object_new:nn { __tag/struct/0 }{ dict } +\hook_gput_code:nnn{shipout/lastpage}{tagpdf} + { + \bool_if:NT \g__tag_active_tree_bool + { + \pdfmanagement_add:nnn { Catalog / MarkInfo } { Marked } { true } + \pdfmanagement_add:nnx + { Catalog } + { StructTreeRoot } + { \pdf_object_ref:n { __tag/struct/0 } } + } + } +\cs_new_protected:Npn \__tag_tree_write_structtreeroot: + { + \__tag_prop_gput:cnx + { g__tag_struct_0_prop } + { ParentTree } + { \pdf_object_ref:n { __tag/tree/parenttree } } + \__tag_prop_gput:cnx + { g__tag_struct_0_prop } + { RoleMap } + { \pdf_object_ref:n { __tag/tree/rolemap } } + \__tag_struct_write_obj:n { 0 } + } +\cs_new_protected:Npn \__tag_tree_write_structelements: + { + \int_step_inline:nnnn {1}{1}{\c@g__tag_struct_abs_int} + { + \__tag_struct_write_obj:n { ##1 } + } + } +\pdf_object_new:nn { __tag/tree/parenttree }{ dict } +\newcounter { g__tag_parenttree_obj_int } +\hook_gput_code:nnn{begindocument}{tagpdf} + { + \int_gset:Nn + \c@g__tag_parenttree_obj_int + { \__tag_ref_value_lastpage:nn{abspage}{100} } + } +\tl_new:N \g__tag_parenttree_objr_tl +\cs_new_protected:Npn \__tag_parenttree_add_objr:nn #1 #2 %#1 StructParent number, #2 objref + { + \tl_gput_right:Nx \g__tag_parenttree_objr_tl + { + #1 \c_space_tl #2 ^^J + } + } +\tl_new:N \l__tag_parenttree_content_tl + +\cs_new_protected:Npn \__tag_tree_fill_parenttree: + { + \int_step_inline:nnnn{1}{1}{\__tag_ref_value_lastpage:nn{abspage}{-1}} %not quite clear if labels are needed. See lua code + { %page ##1 + \prop_clear:N \l__tag_tmpa_prop + \int_step_inline:nnnn{1}{1}{\__tag_ref_value_lastpage:nn{tagmcabs}{-1}} + { + %mcid####1 + \int_compare:nT + {\__tag_ref_value:enn{mcid-####1}{tagabspage}{-1}=##1} %mcid is on current page + {% yes + \prop_put:Nxx + \l__tag_tmpa_prop + {\__tag_ref_value:enn{mcid-####1}{tagmcid}{-1}} + {\prop_item:Nn \g__tag_mc_parenttree_prop {####1}} + } + } + \tl_put_right:Nx\l__tag_parenttree_content_tl + { + \int_eval:n {##1-1}\c_space_tl + [\c_space_tl %] + } + \int_step_inline:nnnn + {0} + {1} + { \prop_count:N \l__tag_tmpa_prop -1 } + { + \prop_get:NnNTF \l__tag_tmpa_prop {####1} \l__tag_tmpa_tl + {% page#1:mcid##1:\l__tag_tmpa_tl :content + \tl_put_right:Nx \l__tag_parenttree_content_tl + { + \pdf_object_if_exist:eT { __tag/struct/\l__tag_tmpa_tl } + { + \pdf_object_ref:e { __tag/struct/\l__tag_tmpa_tl } + } + \c_space_tl + } + } + { + \msg_warning:nn { tag } {tree-mcid-index-wrong} + } + } + \tl_put_right:Nn + \l__tag_parenttree_content_tl + {%[ + ]^^J + } + } + } +\cs_new_protected:Npn \__tag_tree_lua_fill_parenttree: + { + \tl_set:Nn \l__tag_parenttree_content_tl + { + \lua_now:e + { + ltx.__tag.func.output_parenttree + ( + \int_use:N\g_shipout_readonly_int + ) + } + } + } +\cs_new_protected:Npn \__tag_tree_write_parenttree: + { + \bool_if:NTF \g__tag_mode_lua_bool + { + \__tag_tree_lua_fill_parenttree: + } + { + \__tag_tree_fill_parenttree: + } + \tl_put_right:NV \l__tag_parenttree_content_tl\g__tag_parenttree_objr_tl + \pdf_object_write:nx { __tag/tree/parenttree } + { + /Nums\c_space_tl [\l__tag_parenttree_content_tl] + } + } +\pdf_object_new:nn { __tag/tree/rolemap }{ dict } +\cs_new_protected:Npn \__tag_tree_write_rolemap: + { + \pdf_object_write:nx { __tag/tree/rolemap } + { + \pdfdict_use:n{g__tag_role/RoleMap_dict} + } + } +\cs_new_protected:Npn \__tag_tree_write_classmap: + { + \tl_clear:N \l__tag_tmpa_tl + \seq_gremove_duplicates:N \g__tag_attr_class_used_seq + \seq_set_map:NNn \l__tag_tmpa_seq \g__tag_attr_class_used_seq + { + /##1\c_space_tl + << + \prop_item:Nn + \g__tag_attr_entries_prop + {##1} + >> + } + \tl_set:Nx \l__tag_tmpa_tl + { + \seq_use:Nn + \l__tag_tmpa_seq + { \iow_newline: } + } + \tl_if_empty:NF + \l__tag_tmpa_tl + { + \pdf_object_new:nn { __tag/tree/classmap }{ dict } + \pdf_object_write:nx + { __tag/tree/classmap } + { \l__tag_tmpa_tl } + \__tag_prop_gput:cnx + { g__tag_struct_0_prop } + { ClassMap } + { \pdf_object_ref:n { __tag/tree/classmap } } + } + } +\pdf_object_new:nn{ __tag/tree/namespaces }{array} +\cs_new_protected:Npn \__tag_tree_write_namespaces: + { + \prop_map_inline:Nn \g__tag_role_NS_prop + { + \pdfdict_if_empty:nF {g__tag_role/RoleMapNS_##1_dict} + { + \pdf_object_write:nx {__tag/RoleMapNS/##1} + { + \pdfdict_use:n {g__tag_role/RoleMapNS_##1_dict} + } + \pdfdict_gput:nnx{g__tag_role/Namespace_##1_dict} + {RoleMapNS}{\pdf_object_ref:n {__tag/RoleMapNS/##1}} + } + \pdf_object_write:nx{tag/NS/##1} + { + \pdfdict_use:n {g__tag_role/Namespace_##1_dict} + } + } + \pdf_object_write:nx {__tag/tree/namespaces} + { + \prop_map_tokens:Nn \g__tag_role_NS_prop{\use_ii:nn} + } + } +\cs_new_protected:Npn \__tag_finish_structure: + { + \bool_if:NT\g__tag_active_tree_bool + { + \hook_use:n {tagpdf/finish/before} + \__tag_tree_write_parenttree: + \__tag_tree_write_rolemap: + \__tag_tree_write_classmap: + \__tag_tree_write_namespaces: + \__tag_tree_write_structelements: %this is rather slow!! + \__tag_tree_write_structtreeroot: + } + } +\hook_gput_code:nnn{begindocument}{tagpdf} + { + \bool_if:NT\g__tag_active_tree_bool + { + \hook_gput_code:nnn{shipout/before} { tagpdf/structparents } + { + \pdfmanagement_add:nnx + { Page } + { StructParents } + { \int_eval:n { \g_shipout_readonly_int} } + } + } + } +%% File: tagpdf-roles.dtx +\__tag_seq_new:N \g__tag_role_tags_seq %to get names (type/NS) from numbers +\__tag_prop_new:N \g__tag_role_tags_prop %to get numbers from names (type/NS) +\prop_new:N \g__tag_role_tags_NS_prop %to namespace info +\prop_new:N \g__tag_role_NS_prop % collect namespaces +\tl_new:N \l__tag_role_tag_tmpa_tl +\tl_new:N \l__tag_role_tag_namespace_tmpa_tl +\tl_new:N \l__tag_role_role_tmpa_tl +\tl_new:N \l__tag_role_role_namespace_tmpa_tl +\cs_new_protected:Npn \__tag_role_NS_new:nnn #1 #2 #3 + { + \pdf_object_new:nn {tag/NS/#1}{dict} + \pdfdict_new:n {g__tag_role/Namespace_#1_dict} + \pdf_object_new:nn {__tag/RoleMapNS/#1}{dict} + \pdfdict_new:n {g__tag_role/RoleMapNS_#1_dict} + \pdfdict_gput:nnn + {g__tag_role/Namespace_#1_dict} + {Type} + {/Namespace} + \pdf_string_from_unicode:nnN{utf8/string}{#2}\l_tmpa_str + \tl_if_empty:NF \l_tmpa_str + { + \pdfdict_gput:nnx + {g__tag_role/Namespace_#1_dict} + {NS} + {\l_tmpa_str} + } + %RoleMapNS is added in tree + \tl_if_empty:nF {#3} + { + \pdfdict_gput:nnx{g__tag_role/Namespace_#1_dict} + {Schema}{#3} + } + \prop_gput:Nnx \g__tag_role_NS_prop {#1}{\pdf_object_ref:n{tag/NS/#1}~} + } +\str_const:Nx \c__tag_role_userNS_id_str + { data:, + \int_to_Hex:n{\int_rand:n {65535}} + \int_to_Hex:n{\int_rand:n {65535}} + - + \int_to_Hex:n{\int_rand:n {65535}} + - + \int_to_Hex:n{\int_rand:n {65535}} + - + \int_to_Hex:n{\int_rand:n {65535}} + - + \int_to_Hex:n{\int_rand:n {16777215}} + \int_to_Hex:n{\int_rand:n {16777215}} + } +\pdf_version_compare:NnT > {1.9} + { + \__tag_role_NS_new:nnn {pdf} {http://iso.org/pdf/ssn}{} + \__tag_role_NS_new:nnn {pdf2} {http://iso.org/pdf2/ssn}{} + \__tag_role_NS_new:nnn {mathml}{http://www.w3.org/1998/Math/MathML}{} + \exp_args:Nnx + \__tag_role_NS_new:nnn {user}{\c__tag_role_userNS_id_str}{} + } +\clist_const:Nn \c__tag_role_sttags_pdf_pdfII_clist + { + Document, %A complete document. This is the root element + %of any structure tree containing + %multiple parts or multiple articles. + Part, %A large-scale division of a document. + Sect, %A container for grouping related content elements. + Div, %A generic block-level element or group of elements + Caption, %A brief portion of text describing a table or figure. + Index, + NonStruct, %probably not needed + H, + H1, + H2, + H3, + H4, + H5, + H6, + P, + L, %list + LI, %list item (around label and list item body) + Lbl, %list label + LBody, %list item body + Table, + TR, %table row + TH, %table header cell + TD, %table data cell + THead, %table header (n rows) + TBody, %table rows + TFoot, %table footer + Span, %generic inline marker + Link, % + Annot, + Figure, + Formula, + Form, + % ruby warichu etc .. + Ruby, + RB, + RT, + Warichu, + WT, + WP, + Artifact % only MC-tag ?... + } + +\clist_const:Nn \c__tag_role_sttags_only_pdf_clist + { + Art, %A relatively self-contained body of text + %constituting a single narrative or exposition + BlockQuote, %A portion of text consisting of one or more paragraphs + %attributed to someone other than the author of the + %surrounding text. + TOC, %A list made up of table of contents item entries + %(structure tag TOCI; see below) and/or other + %nested table of contents entries + TOCI, %An individual member of a table of contents. + %This entry's children can be any of the following structure tags: + %Lbl,Reference,NonStruct,P,TOC + Index, + Private, + Quote, %inline quote + Note, %footnote, endnote. Lbl can be child + Reference, %A citation to content elsewhere in the document. + BibEntry, %bibentry + Code + } + +\clist_const:Nn \c__tag_role_sttags_only_pdfII_clist + { + DocumentFragment + ,Aside + ,H7 + ,H8 + ,H9 + ,H10 + ,Title + ,FENote + ,Sub + ,Em + ,Strong + ,Artifact + } + +\clist_const:Nn \c__tag_role_sttags_mathml_clist + { + abs + ,and + ,annotation + ,apply + ,approx + ,arccos + ,arccosh + ,arccot + ,arccoth + ,arccsc + ,arccsch + ,arcsec + ,arcsech + ,arcsin + ,arcsinh + ,arctan + ,arctanh + ,arg + ,bind + ,bvar + ,card + ,cartesianproduct + ,cbytes + ,ceiling + ,cerror + ,ci + ,cn + ,codomain + ,complexes + ,compose + ,condition + ,conjugate + ,cos + ,cosh + ,cot + ,coth + ,cs + ,csc + ,csch + ,csymbol + ,curl + ,declare + ,degree + ,determinant + ,diff + ,divergence + ,divide + ,domain + ,domainofapplication + ,emptyset + ,eq + ,equivalent + ,eulergamma + ,exists + ,exp + ,exponentiale + ,factorial + ,factorof + ,false + ,floor + ,fn + ,forall + ,gcd + ,geq + ,grad + ,gt + ,ident + ,image + ,imaginary + ,imaginaryi + ,implies + ,in + ,infinity + ,int + ,integers + ,intersect + ,interval + ,inverse + ,lambda + ,laplacian + ,lcm + ,leq + ,limit + ,ln + ,log + ,logbase + ,lowlimit + ,lt + ,maction + ,maligngroup + ,malignmark + ,math + ,matrix + ,matrixrow + ,max + ,mean + ,median + ,menclose + ,merror + ,mfenced + ,mfrac + ,mglyph + ,mi + ,min + ,minus + ,mlabeledtr + ,mlongdiv + ,mmultiscripts + ,mn + ,mo + ,mode + ,moment + ,momentabout + ,mover + ,mpadded + ,mphantom + ,mprescripts + ,mroot + ,mrow + ,ms + ,mscarries + ,mscarry + ,msgroup + ,msline + ,mspace + ,msqrt + ,msrow + ,mstack + ,mstyle + ,msub + ,msubsup + ,msup + ,mtable + ,mtd + ,mtext + ,mtr + ,munder + ,munderover + ,naturalnumbers + ,neq + ,none + ,not + ,notanumber + ,notin + ,notprsubset + ,notsubset + ,or + ,otherwise + ,outerproduct + ,partialdiff + ,pi + ,piece + ,piecewise + ,plus + ,power + ,primes + ,product + ,prsubset + ,quotient + ,rationals + ,real + ,reals + ,reln + ,rem + ,root + ,scalarproduct + ,sdev + ,sec + ,sech + ,selector + ,semantics + ,sep + ,set + ,setdiff + ,share + ,sin + ,sinh + ,subset + ,sum + ,tan + ,tanh + ,tendsto + ,times + ,transpose + ,true + ,union + ,uplimit + ,variance + ,vector + ,vectorproduct + ,xor + } + +\prop_const_from_keyval:Nn \c__tag_role_sttags_pdfII_to_pdf_prop + { + DocumentFragment = Art, + Aside = Note, + Title = H1, + Sub = Span, + H7 = H6 , + H8 = H6 , + H9 = H6 , + H10 = H6, + FENote= Note, + Em = Span, + Strong= Span, + } + +\clist_map_inline:Nn \c__tag_role_sttags_pdf_pdfII_clist + { + \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 } + \prop_gput:Nnn \g__tag_role_tags_NS_prop { #1 }{ pdf2 } + } +\clist_map_inline:Nn \c__tag_role_sttags_only_pdf_clist + { + \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 } + \prop_gput:Nnn \g__tag_role_tags_NS_prop { #1 }{ pdf } + } +\clist_map_inline:Nn \c__tag_role_sttags_only_pdfII_clist + { + \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 } + \prop_gput:Nnn \g__tag_role_tags_NS_prop { #1 }{ pdf2 } } +\pdf_version_compare:NnT > {1.9} + { + \clist_map_inline:Nn \c__tag_role_sttags_mathml_clist + { + \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 } + \prop_gput:Nnn \g__tag_role_tags_NS_prop { #1 }{ mathml } + } + } +\int_step_inline:nnnn { 1 }{ 1 }{ \seq_count:N \g__tag_role_tags_seq } + { + \__tag_prop_gput:Nxn \g__tag_role_tags_prop + { + \seq_item:Nn \g__tag_role_tags_seq { #1 } + } + { #1 } + } +\pdfdict_new:n {g__tag_role/RoleMap_dict} +\cs_new_protected:Nn \__tag_role_add_tag:nn %(new) name, reference to old + { + \prop_if_in:NnF \g__tag_role_tags_prop {#1} + { + \int_compare:nNnT {\l__tag_loglevel_int} > { 0 } + { + \msg_info:nnn { tag }{new-tag}{#1} + } + \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 } + \__tag_prop_gput:Nnx \g__tag_role_tags_prop { #1 } + { + \seq_count:N \g__tag_role_tags_seq + } + \prop_gput:Nnn \g__tag_role_tags_NS_prop { #1 }{ user } + } + \__tag_check_add_tag_role:nn {#1}{#2} + \tl_if_empty:nF { #2 } + { + \pdfdict_gput:nnx {g__tag_role/RoleMap_dict} + {#1} + {\pdf_name_from_unicode_e:n{#2}} + } + } +\cs_generate_variant:Nn \__tag_role_add_tag:nn {VV} + +\pdf_version_compare:NnT < {2.0} + { + \prop_map_inline:Nn \c__tag_role_sttags_pdfII_to_pdf_prop + { + \__tag_role_add_tag:nn {#1}{#2} + } + } + +\cs_new_protected:Nn \__tag_role_add_tag:nnnn %tag/namespace/role/namespace + { + \int_compare:nNnT {\l__tag_loglevel_int} > { 0 } + { + \msg_info:nnn { tag }{new-tag}{#1} + } + \__tag_seq_gput_right:Nn \g__tag_role_tags_seq { #1 } + \__tag_prop_gput:Nnx \g__tag_role_tags_prop { #1 } + { + \seq_count:N \g__tag_role_tags_seq + } + \prop_gput:Nnn \g__tag_role_tags_NS_prop { #1 }{ #2 } + \__tag_check_add_tag_role:nn {#1}{#3} + \pdfdict_gput:nnx {g__tag_role/RoleMapNS_#2_dict}{#1} + { + [ + \pdf_name_from_unicode_e:n{#3} + \c_space_tl + \pdf_object_ref:n {tag/NS/#4} + ] + } + } +\cs_generate_variant:Nn \__tag_role_add_tag:nnnn {VVVV} +\keys_define:nn { __tag / tag-role } + { + ,tag .tl_set:N = \l__tag_role_tag_tmpa_tl + ,tag-namespace .tl_set:N = \l__tag_role_tag_namespace_tmpa_tl + ,role .tl_set:N = \l__tag_role_role_tmpa_tl + ,role-namespace .tl_set:N = \l__tag_role_role_namespace_tmpa_tl + } + +\keys_define:nn { __tag / setup } + { + add-new-tag .code:n = + { + \keys_set_known:nnnN + {__tag/tag-role} + { + tag-namespace=user, + role-namespace=, %so that we can test for it. + #1 + }{__tag/tag-role}\l_tmpa_tl + \tl_if_empty:NF \l_tmpa_tl + { + \exp_args:NNno \seq_set_split:Nnn \l_tmpa_seq { / } {\l_tmpa_tl/} + \tl_set:Nx \l__tag_role_tag_tmpa_tl { \seq_item:Nn \l_tmpa_seq {1} } + \tl_set:Nx \l__tag_role_role_tmpa_tl { \seq_item:Nn \l_tmpa_seq {2} } + } + \tl_if_empty:NT \l__tag_role_role_namespace_tmpa_tl + { + \prop_get:NVNTF + \g__tag_role_tags_NS_prop + \l__tag_role_role_tmpa_tl + \l__tag_role_role_namespace_tmpa_tl + { + \prop_if_in:NVF\g__tag_role_NS_prop \l__tag_role_role_namespace_tmpa_tl + { + \tl_set:Nn \l__tag_role_role_namespace_tmpa_tl {user} + } + } + { + \tl_set:Nn \l__tag_role_role_namespace_tmpa_tl {user} + } + } + \pdf_version_compare:NnTF < {2.0} + { + %TODO add check for emptyness? + \__tag_role_add_tag:VV + \l__tag_role_tag_tmpa_tl + \l__tag_role_role_tmpa_tl + } + { + \__tag_role_add_tag:VVVV + \l__tag_role_tag_tmpa_tl + \l__tag_role_tag_namespace_tmpa_tl + \l__tag_role_role_tmpa_tl + \l__tag_role_role_namespace_tmpa_tl + } + } + } +%% File: tagpdf-struct.dtx +\newcounter { g__tag_struct_abs_int } +\int_gzero:N \c@g__tag_struct_abs_int +\__tag_seq_new:N \g__tag_struct_objR_seq +\seq_new:N \g__tag_struct_stack_seq +\seq_gpush:Nn \g__tag_struct_stack_seq {0} +\seq_new:N \g__tag_struct_tag_stack_seq +\seq_gpush:Nn \g__tag_struct_tag_stack_seq {Root} +\tl_new:N \g__tag_struct_stack_current_tl +\tl_new:N \l__tag_struct_stack_parent_tmpa_tl + +\seq_const_from_clist:Nn \c__tag_struct_StructTreeRoot_entries_seq + {%p. 857/858 + Type, % always /StructTreeRoot + K, % kid, dictionary or array of dictionaries + IDTree, % currently unused + ParentTree, % required,obj ref to the parent tree + ParentTreeNextKey, % optional + RoleMap, + ClassMap, + Namespaces + } + +\seq_const_from_clist:Nn \c__tag_struct_StructElem_entries_seq + {%p 858 f + Type, %always /StructElem + S, %tag/type + P, %parent + ID, %optional + Ref, %optional, pdf 2.0 Use? + Pg, %obj num of starting page, optional + K, %kids + A, %attributes, probably unused + C, %class "" + %R, %attribute revision number, irrelevant for us as we + % don't update/change existing PDF and (probably) + % deprecated in PDF 2.0 + T, %title, value in () or <> + Lang, %language + Alt, % value in () or <> + E, % abreviation + ActualText, + AF, %pdf 2.0, array of dict, associated files + NS, %pdf 2.0, dict, namespace + PhoneticAlphabet, %pdf 2.0 + Phoneme %pdf 2.0 + } +\tl_new:N \g__tag_struct_tag_tl +\tl_new:N \g__tag_struct_tag_NS_tl +\tl_new:N \l__tag_struct_key_label_tl +\bool_new:N \l__tag_struct_elem_stash_bool +\cs_new:Npn \__tag_struct_output_prop_aux:nn #1 #2 %#1 num, #2 key + { + \prop_if_in:cnT + { g__tag_struct_#1_prop } + { #2 } + { + \c_space_tl/#2~ \prop_item:cn{ g__tag_struct_#1_prop } { #2 } + } + } + +\cs_new_protected:Npn \__tag_new_output_prop_handler:n #1 + { + \cs_new:cn { __tag_struct_output_prop_#1:n } + { + \__tag_struct_output_prop_aux:nn {#1}{##1} + } + } +\tl_gset:Nn \g__tag_struct_stack_current_tl {0} + +\__tag_prop_new:c { g__tag_struct_0_prop } +\__tag_new_output_prop_handler:n {0} +\__tag_seq_new:c { g__tag_struct_kids_0_seq } + +\__tag_prop_gput:cnn + { g__tag_struct_0_prop } + { Type } + { /StructTreeRoot } + +\__tag_prop_gput:cnx + { g__tag_struct_0_prop } + { Namespaces } + { \pdf_object_ref:n { __tag/tree/namespaces } } +\cs_new_protected:Npn \__tag_struct_kid_mc_gput_right:nn #1 #2 %#1 structure num, #2 MCID absnum% + { + \__tag_seq_gput_right:cx + { g__tag_struct_kids_#1_seq } + { + << + /Type \c_space_tl /MCR \c_space_tl + /Pg + \c_space_tl + \pdf_pageobject_ref:n { \__tag_ref_value:enn{mcid-#2}{tagabspage}{1} } + /MCID \c_space_tl \__tag_ref_value:enn{mcid-#2}{tagmcid}{1} + >> + } + } +\cs_new_protected:Npn\__tag_struct_kid_struct_gput_right:nn #1 #2 %#1 num of parent struct, #2 kid struct + { + \__tag_seq_gput_right:cx + { g__tag_struct_kids_#1_seq } + { + \pdf_object_ref:n { __tag/struct/#2 } + } + } -\RequirePackage { tagpdf-struct-code } -\RequirePackage { tagpdf-space-code } +\cs_generate_variant:Nn \__tag_struct_kid_struct_gput_right:nn {xx} +\cs_new_protected:Npn\__tag_struct_kid_OBJR_gput_right:nn #1 #2 %#1 num of parent struct, + %#2 obj reference + { + \pdf_object_unnamed_write:nn + { dict } + { + /Type/OBJR/Obj~#2 + } + \__tag_seq_gput_right:cx + { g__tag_struct_kids_#1_seq } + { + \pdf_object_ref_last: + } + } + +\cs_generate_variant:Nn\__tag_struct_kid_OBJR_gput_right:nn { xx } + +\cs_new_protected:Npn\__tag_struct_exchange_kid_command:N #1 %#1 = seq var + { + \seq_gpop_left:NN #1 \l__tag_tmpa_tl + \regex_replace_once:nnN + { \c{\__tag_mc_insert_mcid_kids:n} } + { \c{\__tag_mc_insert_mcid_single_kids:n} } + \l__tag_tmpa_tl + \seq_gput_left:NV #1 \l__tag_tmpa_tl + } + +\cs_generate_variant:Nn\__tag_struct_exchange_kid_command:N { c } +\cs_new_protected:Npn \__tag_struct_fill_kid_key:n #1 %#1 is the struct num + { + \int_case:nnF + { + \seq_count:c + { + g__tag_struct_kids_#1_seq + } + } + { + { 0 } + { } %no kids, do nothing + { 1 } % 1 kid, insert + { + % in this case we need a special command in + % luamode to get the array right. See issue #13 + \bool_if:NT\g__tag_mode_lua_bool + { + \__tag_struct_exchange_kid_command:c + {g__tag_struct_kids_#1_seq} + } + \__tag_prop_gput:cnx { g__tag_struct_#1_prop } {K} + { + \seq_item:cn + { + g__tag_struct_kids_#1_seq + } + {1} + } + } % + } + { %many kids, use an array + \__tag_prop_gput:cnx { g__tag_struct_#1_prop } {K} + { + [ + \seq_use:cn + { + g__tag_struct_kids_#1_seq + } + { + \c_space_tl + } + ] + } + } + } + +\cs_new_protected:Npn \__tag_struct_get_dict_content:nN #1 #2 %#1: stucture num + { + \tl_clear:N #2 + \seq_map_inline:cn + { + c__tag_struct_ + \int_compare:nNnTF{#1}={0}{StructTreeRoot}{StructElem} + _entries_seq + } + { + \tl_put_right:Nx + #2 + { + \prop_if_in:cnT + { g__tag_struct_#1_prop } + { ##1 } + { + \c_space_tl/##1~\prop_item:cn{ g__tag_struct_#1_prop } { ##1 } + } + } + } + } +\cs_new_protected:Npn \__tag_struct_write_obj:n #1 % #1 is the struct num + { + \pdf_object_if_exist:nTF { __tag/struct/#1 } + { + \__tag_struct_fill_kid_key:n { #1 } + \__tag_struct_get_dict_content:nN { #1 } \l__tag_tmpa_tl + \exp_args:Nx + \pdf_object_write:nx + { __tag/struct/#1 } + { + \l__tag_tmpa_tl + } + } + { + \msg_error:nnn { tag } { struct-no-objnum } { #1} + } + } +\cs_new_protected:Npn \__tag_struct_insert_annot:nn #1 #2 %#1 object reference to the annotation/xform + %#2 structparent number + { + \bool_if:NT \g__tag_active_struct_bool + { + %get the number of the parent structure: + \seq_get:NNF + \g__tag_struct_stack_seq + \l__tag_struct_stack_parent_tmpa_tl + { + \msg_error:nn { tag } { struct-faulty-nesting } + } + %put the obj number of the annot in the kid entry, this also creates + %the OBJR object + \__tag_struct_kid_OBJR_gput_right:xx + { + \l__tag_struct_stack_parent_tmpa_tl + } + { + #1 % + } + % add the parent obj number to the parent tree: + \exp_args:Nnx + \__tag_parenttree_add_objr:nn + { + #2 + } + { + \pdf_object_ref:e { __tag/struct/\l__tag_struct_stack_parent_tmpa_tl } + } + % increase the int: + \stepcounter{ g__tag_parenttree_obj_int } + } + } +\cs_new:Npn \__tag_get_data_struct_tag: + { + \exp_args:Ne + \tl_tail:n + { + \prop_item:cn {g__tag_struct_\g__tag_struct_stack_current_tl _prop}{S} + } + } +\keys_define:nn { __tag / struct } + { + label .tl_set:N = \l__tag_struct_key_label_tl, + stash .bool_set:N = \l__tag_struct_elem_stash_bool, + tag .code:n = % S property + { + \seq_set_split:Nne \l__tag_tmpa_seq { / } {#1/\prop_item:Nn\g__tag_role_tags_NS_prop{#1}} + \tl_gset:Nx \g__tag_struct_tag_tl { \seq_item:Nn\l__tag_tmpa_seq {1} } + \tl_gset:Nx \g__tag_struct_tag_NS_tl { \seq_item:Nn\l__tag_tmpa_seq {2} } + \__tag_check_structure_tag:N \g__tag_struct_tag_tl + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { S } + { \pdf_name_from_unicode_e:n{ \g__tag_struct_tag_tl} } % + \prop_get:NVNT \g__tag_role_NS_prop\g__tag_struct_tag_NS_tl\l__tag_tmpa_tl + { + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { NS } + { \l__tag_tmpa_tl } % + } + }, + title .code:n = % T property + { + \str_set_convert:Nnon + \l__tag_tmpa_str + { #1 } + { default } + { utf16/hex } + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { T } + { <\l__tag_tmpa_str> } + }, + title-o .code:n = % T property + { + \str_set_convert:Nnon + \l__tag_tmpa_str + { #1 } + { default } + { utf16/hex } + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { T } + { <\l__tag_tmpa_str> } + }, + alttext .code:n = % Alt property + { + \str_set_convert:Nnon + \l__tag_tmpa_str + { #1 } + { default } + { utf16/hex } + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { Alt } + { <\l__tag_tmpa_str> } + }, + alttext-o .code:n = % Alt property + { + \str_set_convert:Noon + \l__tag_tmpa_str + { #1 } + { default } + { utf16/hex } + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { Alt } + { <\l__tag_tmpa_str> } + }, + actualtext .code:n = % ActualText property + { + \str_set_convert:Nnon + \l__tag_tmpa_str + { #1 } + { default } + { utf16/hex } + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { ActualText } + { <\l__tag_tmpa_str>} + }, + actualtext-o .code:n = % ActualText property + { + \str_set_convert:Noon + \l__tag_tmpa_str + { #1 } + { default } + { utf16/hex } + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { ActualText } + { <\l__tag_tmpa_str>} + }, + lang .code:n = % Lang property + { + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { Lang } + { (#1) } + }, + ref .code:n = % Lang property + { + \tl_clear:N\l__tag_tmpa_tl + \clist_map_inline:nn {#1} + { + \tl_put_right:Nx \l__tag_tmpa_tl + {~\ref_value:nn{tagpdfstruct-##1}{tagstructobj} } + } + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { Ref } + { [\l__tag_tmpa_tl] } + }, + E .code:n = % E property + { + \str_set_convert:Nnon + \l__tag_tmpa_str + { #1 } + { default } + { utf16/hex } + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { E } + { <\l__tag_tmpa_str> } + }, + } +\keys_define:nn { __tag / struct } + { + AF .code:n = % AF property + { + \pdf_object_if_exist:nTF {#1} + { + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { AF } + { \pdf_object_ref:n {#1} } + } + { + + } + }, + ,AFinline .code:n = + { + \group_begin: + \pdf_object_if_exist:eF {__tag/fileobj\int_use:N\c@g__tag_struct_abs_int} + { + \pdffile_embed_stream:nxx + {#1} + {tag-AFfile\int_use:N\c@g__tag_struct_abs_int.txt} + {__tag/fileobj\int_use:N\c@g__tag_struct_abs_int} + } + \__tag_prop_gput:cnx + { g__tag_struct_\int_use:N\c@g__tag_struct_abs_int _prop } + { AF } + { \pdf_object_ref:e {__tag/fileobj\int_use:N\c@g__tag_struct_abs_int } } + \group_end: + } + ,AFinline-o .code:n = + { + \group_begin: + \pdf_object_if_exist:eF {__tag/fileobj\int_use:N\c@g__tag_struct_abs_int} + { + \pdffile_embed_stream:oxx + {#1} + {tag-AFfile\int_use:N\c@g__tag_struct_abs_int.txt} + {__tag/fileobj\int_use:N\c@g__tag_struct_abs_int} + } + \__tag_prop_gput:cnx + { g__tag_struct_\int_use:N\c@g__tag_struct_abs_int _prop } + { AF } + { \pdf_object_ref:e {__tag/fileobj\int_use:N\c@g__tag_struct_abs_int } } + \group_end: + } + } +\cs_new_protected:Npn \tag_struct_begin:n #1 %#1 key-val + { + \__tag_check_if_active_struct:T + { + \group_begin: + \int_gincr:N \c@g__tag_struct_abs_int + \__tag_prop_new:c { g__tag_struct_\int_eval:n { \c@g__tag_struct_abs_int }_prop } + \__tag_new_output_prop_handler:n {\int_eval:n { \c@g__tag_struct_abs_int }} + \__tag_seq_new:c { g__tag_struct_kids_\int_eval:n { \c@g__tag_struct_abs_int }_seq} + \exp_args:Ne + \pdf_object_new:nn + { __tag/struct/\int_eval:n { \c@g__tag_struct_abs_int } } + { dict } + \__tag_prop_gput:cno + { g__tag_struct_\int_eval:n { \c@g__tag_struct_abs_int }_prop } + { Type } + { /StructElem } + \keys_set:nn { __tag / struct} { #1 } + \__tag_check_structure_has_tag:n { \int_eval:n {\c@g__tag_struct_abs_int} } + \tl_if_empty:NF + \l__tag_struct_key_label_tl + { + \__tag_ref_label:en{tagpdfstruct-\l__tag_struct_key_label_tl}{struct} + } + %get the potential parent from the stack: + \seq_get:NNF + \g__tag_struct_stack_seq + \l__tag_struct_stack_parent_tmpa_tl + { + \msg_error:nn { tag } { struct-faulty-nesting } + } + \seq_gpush:NV \g__tag_struct_stack_seq \c@g__tag_struct_abs_int + \seq_gpush:NV \g__tag_struct_tag_stack_seq \g__tag_struct_tag_tl + \tl_gset:NV \g__tag_struct_stack_current_tl \c@g__tag_struct_abs_int + %\seq_show:N \g__tag_struct_stack_seq + \bool_if:NF + \l__tag_struct_elem_stash_bool + {%set the parent + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { P } + { + \pdf_object_ref:e { __tag/struct/\l__tag_struct_stack_parent_tmpa_tl } + } + %record this structure as kid: + %\tl_show:N \g__tag_struct_stack_current_tl + %\tl_show:N \l__tag_struct_stack_parent_tmpa_tl + \__tag_struct_kid_struct_gput_right:xx + { \l__tag_struct_stack_parent_tmpa_tl } + { \g__tag_struct_stack_current_tl } + %\prop_show:c { g__tag_struct_\g__tag_struct_stack_current_tl _prop } + %\seq_show:c {g__tag_struct_kids_\l__tag_struct_stack_parent_tmpa_tl _seq} + } + %\prop_show:c { g__tag_struct_\g__tag_struct_stack_current_tl _prop } + %\seq_show:c {g__tag_struct_kids_\l__tag_struct_stack_parent_tmpa_tl _seq} + \group_end: + } + } + +\cs_new_protected:Nn \tag_struct_end: + { %take the current structure num from the stack: + %the objects are written later, lua mode hasn't all needed info yet + %\seq_show:N \g__tag_struct_stack_seq + \__tag_check_if_active_struct:T + { + \seq_gpop:NN \g__tag_struct_tag_stack_seq \l__tag_tmpa_tl + \seq_gpop:NNTF \g__tag_struct_stack_seq \l__tag_tmpa_tl + { + \__tag_check_info_closing_struct:o { \g__tag_struct_stack_current_tl } + } + { \__tag_check_no_open_struct: } + % get the previous one, shouldn't be empty as the root should be there + \seq_get:NNTF \g__tag_struct_stack_seq \l__tag_tmpa_tl + { + \tl_gset:NV \g__tag_struct_stack_current_tl \l__tag_tmpa_tl + } + { + \__tag_check_no_open_struct: + } + \seq_get:NNT \g__tag_struct_tag_stack_seq \l__tag_tmpa_tl + { + \tl_gset:NV \g__tag_struct_tag_tl \l__tag_tmpa_tl + } + } + } +\cs_new_protected:Nn \tag_struct_use:n %#1 is the label + { + \__tag_check_if_active_struct:T + { + \prop_if_exist:cTF + { g__tag_struct_\__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{unknown}_prop } % + { + \__tag_check_struct_used:n {#1} + %add the label structure as kid to the current structure (can be the root) + \__tag_struct_kid_struct_gput_right:xx + { \g__tag_struct_stack_current_tl } + { \__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0} } + %add the current structure to the labeled one as parents + \__tag_prop_gput:cnx + { g__tag_struct_\__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0}_prop } + { P } + { + \pdf_object_ref:e { __tag/struct/\g__tag_struct_stack_current_tl } + } + } + { + \msg_warning:nnn{ tag }{struct-label-unknown}{#1} + } + } + } +\cs_new_protected:Npn \tag_struct_insert_annot:nn #1 #2 %#1 should be an object reference + %#2 struct parent num + { + \__tag_check_if_active_struct:T + { + \__tag_struct_insert_annot:nn {#1}{#2} + } + } + +\cs_generate_variant:Nn \tag_struct_insert_annot:nn {xx} +\cs_new:Npn \tag_struct_parent_int: {\int_use:c { c@g__tag_parenttree_obj_int }} + + +\prop_new:N \g__tag_attr_entries_prop +\seq_new:N \g__tag_attr_class_used_seq +\tl_new:N \l__tag_attr_value_tl +\prop_new:N \g__tag_attr_objref_prop %will contain obj num of used attributes +\cs_new_protected:Npn \__tag_attr_new_entry:nn #1 #2 %#1:name, #2: content + { + \prop_gput:Nnn \g__tag_attr_entries_prop + {#1}{#2} + } + +\keys_define:nn { __tag / setup } + { + newattribute .code:n = + { + \__tag_attr_new_entry:nn #1 + } + } +\keys_define:nn { __tag / struct } + { + attribute-class .code:n = + { + \clist_set:No \l__tag_tmpa_clist { #1 } + \seq_set_from_clist:NN \l__tag_tmpa_seq \l__tag_tmpa_clist + \seq_map_inline:Nn \l__tag_tmpa_seq + { + \prop_if_in:NnF \g__tag_attr_entries_prop {##1} + { + \msg_error:nnn { tag } { attr-unknown } { ##1 } + } + \seq_gput_left:Nn\g__tag_attr_class_used_seq { ##1} + } + \seq_set_map:NNn \l__tag_tmpb_seq \l__tag_tmpa_seq + { + /##1 + } + \tl_set:Nx \l__tag_tmpa_tl + { + \int_compare:nT { \seq_count:N \l__tag_tmpa_seq > 1 }{[} + \seq_use:Nn \l__tag_tmpb_seq { \c_space_tl } + \int_compare:nT { \seq_count:N \l__tag_tmpa_seq > 1 }{]} + } + \int_compare:nT { \seq_count:N \l__tag_tmpa_seq > 0 } + { + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { C } + { \l__tag_tmpa_tl } + %\prop_show:c { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + } + } + } +\keys_define:nn { __tag / struct } + { + attribute .code:n = % A property (attribute, value currently a dictionary) + { + \clist_set:No \l__tag_tmpa_clist { #1 } + \seq_set_from_clist:NN \l__tag_tmpa_seq \l__tag_tmpa_clist + \tl_set:Nx \l__tag_attr_value_tl + { + \int_compare:nT { \seq_count:N \l__tag_tmpa_seq > 1 }{[}%] + } + \seq_map_inline:Nn \l__tag_tmpa_seq + { + \prop_if_in:NnF \g__tag_attr_entries_prop {##1} + { + \msg_error:nnn { tag } { attr-unknown } { ##1 } + } + \prop_if_in:NnF \g__tag_attr_objref_prop {##1} + {%\prop_show:N \g__tag_attr_entries_prop + \pdf_object_unnamed_write:nx + { dict } + { + \prop_item:Nn\g__tag_attr_entries_prop {##1} + } + \prop_gput:Nnx \g__tag_attr_objref_prop {##1} {\pdf_object_ref_last:} + } + \tl_put_right:Nx \l__tag_attr_value_tl + { + \c_space_tl + \prop_item:Nn \g__tag_attr_objref_prop {##1} + } + % \tl_show:N \l__tag_attr_value_tl + } + \tl_put_right:Nx \l__tag_attr_value_tl + { %[ + \int_compare:nT { \seq_count:N \l__tag_tmpa_seq > 1 }{]}% + } + % \tl_show:N \l__tag_attr_value_tl + \__tag_prop_gput:cnx + { g__tag_struct_\int_eval:n {\c@g__tag_struct_abs_int}_prop } + { A } + { \l__tag_attr_value_tl } + }, + } +%% File: tagpdf-space.dtx +\sys_if_engine_pdftex:T + { + \sys_if_output_pdf:TF + { + \pdfglyphtounicode{space}{0020} + \keys_define:nn { __tag / setup } + { + interwordspace .choices:nn = { true, on } { \pdfinterwordspaceon }, + interwordspace .choices:nn = { false, off }{ \pdfinterwordspaceon }, + interwordspace .default:n = true, + show-spaces .bool_set:N = \l__tag_showspaces_bool + } + } + { + \keys_define:nn { __tag / setup } + { + interwordspace .choices:nn = { true, on, false, off } + { \msg_warning:nnn {tag}{sys-no-interwordspace}{dvi} }, + interwordspace .default:n = true, + show-spaces .bool_set:N = \l__tag_showspaces_bool + } + } + } + +\sys_if_engine_luatex:T + { + \keys_define:nn { __tag / setup } + { + interwordspace .choices:nn = + { true, on } + { + \bool_gset_true:N \g__tag_active_space_bool + \lua_now:e{ltx.__tag.func.markspaceon()} + }, + interwordspace .choices:nn = + { false, off } + { + \bool_gset_false:N \g__tag_active_space_bool + \lua_now:e{ltx.__tag.func.markspaceoff()} + }, + interwordspace .default:n = true, + show-spaces .choice:, + show-spaces / true .code:n = + {\lua_now:e{ltx.__tag.trace.showspaces=true}}, + show-spaces / false .code:n = + {\lua_now:e{ltx.__tag.trace.showspaces=nil}}, + show-spaces .default:n = true + } + } + +\sys_if_engine_xetex:T + { + \keys_define:nn { __tag / setup } + { + interwordspace .choices:nn = { true, on } + { \msg_warning:nnn {tag}{sys-no-interwordspace}{xetex} }, + interwordspace .choices:nn = { false, off } + { \msg_warning:nnn {tag}{sys-no-interwordspace}{xetex} }, + interwordspace .default:n = true, + show-spaces .bool_set:N = \l__tag_showspaces_bool + } + } +\sys_if_engine_luatex:T + { + \cs_new_protected:Nn \__tag_fakespace: + { + \group_begin: + \lua_now:e{ltx.__tag.func.fakespace()} + \skip_horizontal:n{\c_zero_skip} + \group_end: + } + } %% %% %% End of file `tagpdf.sty'. |