diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx | 498 |
1 files changed, 498 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx new file mode 100644 index 00000000000..145b1509712 --- /dev/null +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx @@ -0,0 +1,498 @@ +% \iffalse meta-comment +% +%% File: tagpdf.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> +%<*package> +\ProvidesExplPackage {tagpdf} {2021/02/23} {0.80} + { A package to experiment with pdf tagging } + +\bool_if:nF + { + \bool_lazy_and_p:nn + {\cs_if_exist_p:N \pdfmanagement_if_active_p:} + { \pdfmanagement_if_active_p: } + } + { %error for now, perhaps warning later. + \PackageError{tagpdf} + { + PDF~resource~management~is~no~active!\MessageBreak + tagpdf~will~no~work. + } + { + Activate~it~with \MessageBreak + \string\RequirePackage{pdfmanagement-testphase}\MessageBreak + \string\DeclareDocumentMetadata{<options>}\MessageBreak + before~\string\documentclass + } + } + +%\debug_on:n{check-declarations,check-expressions,deprecation} + +%map internal tag to package name +\prop_if_exist:NT \g_msg_module_name_prop + { + \prop_gput:Nnn \g_msg_module_name_prop { tag }{ tagpdf } + } + +% storing internal names to my name space: +\cs_set_eq:NN \@@_tex_global:D \tex_global:D + +%%% package options +\bool_new:N\g_@@_mode_lua_bool + +\DeclareOption {luamode} { \sys_if_engine_luatex:T { \bool_gset_true:N \g_@@_mode_lua_bool } } +\DeclareOption {genericmode}{ \bool_gset_false:N\g_@@_mode_lua_bool } +\ExecuteOptions{luamode} +\ProcessOptions + +%%% some packages +%references use l3ref-tmp +\RequirePackage{l3ref-tmp} + %================ + % temporary code + % =============== + % faking the LastPage label: + \cs_new_protected:Npn \@@_lastpagelabel: + { + \legacy_if:nT { @filesw } + { + \exp_args:NNnx \exp_args:NNx\iow_now:Nn \@auxout + { + \token_to_str:N \newlabeldata + {@@_LastPage} + { + {abspage} { \int_use:N \g_shipout_readonly_int} + {tagmcabs}{ \int_use:N \c@g_@@_MCID_abs_int } + } + } + } + } + + \AddToHook{enddocument/afterlastpage} + {\@@_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 + { + \exp_args:Nee + \__ref_value:nnn + { \tl_to_str:n {#1} } { \tl_to_str:n {#2} } {#3} + } + \cs_new:Npn \__ref_value:nnn #1#2#3 + { + \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_@@_struct_abs_int } +\ref_attribute_gset:nnnn {tagstructobj} {}{now} + { + \exp_args:Ne + \pdf_object_if_exist:nT {c__tag_struct_ \int_use:N \c@g__tag_struct_abs_int _obj} + { + \pdf_object_ref:e{c__tag_struct_ \int_use:N \c@g_@@_struct_abs_int _obj} + } + } + % 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_@@_MCID_abs_int } +\ref_attribute_gset:nnnn {tagmcid } {0}{now} { \int_use:N \g_@@_MCID_tmp_bypage_int } +%============ +% lists +%============ +\clist_const:Nn \c_@@_refmc_clist {tagabspage,tagmcabs,tagmcid} %mc is new!! +\clist_const:Nn \c_@@_refstruct_clist {tagstruct,tagstructobj} +%================= +% command to set a label +%================ +\cs_generate_variant:Nn \ref_label:nn { nv } +\cs_new_protected:Npn \@@_ref_label:nn #1 #2 %#1 label, #2 name of list mc or struct + { + \@bsphack + \ref_label:nv {#1}{c_@@_ref#2_clist} + \@esphack + } +%============== +% command to retrieve the value +%=============== +\cs_new:Npn \@@_ref_value:nnn #1 #2 #3 %#1 label, #2 attribute, #3 default + { + \ref_value:nnn {#1}{#2}{#3} + } +%=============== +% the LastPage label has a different name, so we need a special command for now +% ============= +\cs_new:Npn \@@_ref_value_lastpage:nn #1 #2 + { + \ref_value:nnn {@@_LastPage}{#1}{#2} + } + +% as ref doesn't expand label names we need variants: +\cs_generate_variant:Nn \@@_ref_label:nn {en} +\cs_generate_variant:Nn \@@_ref_value:nnn {enn} + +\RequirePackage{etoolbox} +%\RequirePackage{l3pdf} +%\RequirePackage{pdfescape} %check if needed +%\RequirePackage{pdftexcmds}%check if needed (expandable commands!) + +%\RequirePackage{l3str-convert} +\cs_generate_variant:Nn \str_set_convert:Nnnn {Nonn, Noon, Nnon } + + + + +%%% tagpdfsetup, +%%% TODO: checks need to be improved +\int_new:N \l_@@_loglevel_int +\tl_new:N \l_@@_tree_tabs_order_tl + +\keys_define:nn { @@ / setup } + { + activate-mc .bool_gset:N = \g_@@_active_mc_bool, + activate-tree .bool_gset:N = \g_@@_active_tree_bool, + activate-struct .bool_gset:N = \g_@@_active_struct_bool, + activate-all .meta:n ={activate-mc,activate-tree,activate-struct}, + check-tags .bool_gset:N = \g_@@_check_tags_bool, + check-tags .initial:n = true, + log .choice:, + log / none .code:n = {\int_set:Nn \l_@@_loglevel_int { 0 }}, + log / v .code:n = {\int_set:Nn \l_@@_loglevel_int { 1 }}, + log / vv .code:n = {\int_set:Nn \l_@@_loglevel_int { 2 }}, + log / vvv .code:n = {\int_set:Nn \l_@@_loglevel_int { 3 }}, + log / all .code:n = {\int_set:Nn \l_@@_loglevel_int { 10 }}, + tagunmarked .bool_gset:N = \g_@@_tagunmarked_bool, + tagunmarked .initial:n = true, + tabsorder .choice:, + tabsorder / row .code:n = %{\tl_set:Nn \l_@@_tree_tabs_order_tl {/Tabs/R}}, + \pdfmanagement_add:nnn { Page } {Tabs}{/R}, + tabsorder / column .code:n = %{\tl_set:Nn \l_@@_tree_tabs_order_tl {/Tabs/C}}, + \pdfmanagement_add:nnn { Page } {Tabs}{/C}, + tabsorder / structure .code:n = %{\tl_set:Nn \l_@@_tree_tabs_order_tl {/Tabs/S}}, + \pdfmanagement_add:nnn { Page } {Tabs}{/S}, + tabsorder / none .code:n = %{\tl_set:Nn \l_@@_tree_tabs_order_tl {}}, + \pdfmanagement_remove:nn {Page} {Tabs}, + tabsorder .initial:n = structure, + uncompress .code:n = {\pdf_uncompress: }, + } +%need to think about the right place ... +%\AtBeginDocument +\hook_gput_code:nnn{begindocument}{tagpdf} + { + \bool_if:NT \g_@@_active_struct_bool + { + \pdfmanagement_add:nnn { Catalog / MarkInfo } { Marked } { true } + } + } +% escape commands are a bit engine specific so have been moved to the backend files. +% commands to escape strings so that they can be safely used in pdf +% currently not much used. But will be needed later, when alt and actualtext are added. +% we probably need the equivalent \pdfescapestring, \pdfescapename \pdfescapehex +% the commands of pdfescape adds an additional layout to allow for babel shorthands +%\cs_set_eq:NN \@@_pdf_escape_string:Nn \EdefEscapeString +%\cs_set_eq:NN \@@_pdf_escape_name:Nn \EdefEscapeName +%\cs_set_eq:NN \@@_pdf_escape_hex:Nn \EdefEscapeHex + +%\cs_set_eq:NN \@@_pdf_escape_string:n \EdefEscapeString +%\cs_set_eq:NN \@@_pdf_escape_name:Nn \EdefEscapeName + +%escape command. They are backend specific as \pdf@escapehex would ignore most chars +%outside the "pdflatex" range + + + + + +% a hook for later code and an absolute page counter +% should be executed before counters are resetted. +% is it used? +\cs_new:Nn \@@_finish_page_hook: { } + +%\AtBeginShipout + +\hook_gput_code:nnn + { shipout/before } + { tagpdf/cnt } + { + \@@_finish_page_hook: + %\int_gincr:N \g_@@_abspage_int + } + + +%testing the engines and loading the backend files +\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} + } + +\sys_if_engine_luatex:T + { + \file_input:n {tagpdf-luatex.def} + } + +\sys_if_engine_pdftex:T + { + \file_input:n {tagpdf-pdftex.def} + } + +\sys_if_output_dvi:T + { + %\PackageError { tagpdf } { dvi~output~is~not~supported~-~aborting }{} + %\tex_endinput:D + } + +\cs_generate_variant:Nn \@@_prop_gput:Nnn { Nxn , Nxx, Nnx , cnn, cxn, cnx, cno} +\cs_generate_variant:Nn \@@_seq_gput_right:Nn { Nx , No, cn, cx } +\cs_generate_variant:Nn \@@_prop_new:N { c } +\cs_generate_variant:Nn \@@_seq_new:N { c } +\cs_generate_variant:Nn \@@_seq_show:N { c } +\cs_generate_variant:Nn \@@_prop_show:N { c } +\cs_generate_variant:Nn \prop_gput:Nnn {Nxx} +\cs_generate_variant:Nn \prop_put:Nnn {Nxx} + +\cs_generate_variant:Nn \pdffile_embed_stream:nnn {nxx,oxx} +\cs_generate_variant:Nn \pdf_object_ref:n {e} + + +% few temp tl +\tl_new:N \g_@@_tmpa_tl +\tl_new:N \l_@@_tmpa_tl +\tl_new:N \l_@@_tmpb_tl +\tl_new:N \l_@@_tmpc_tl +\tl_new:N \l_@@_tmpd_tl +\tl_new:N \l_@@_tmpe_tl +\str_new:N \l_@@_tmpa_str + +% helper function to get the propcount. +% use as \prop_map_function:NN PROP { \@@_prop_count:nn -1 } +\cs_new:Nn\@@_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 } +% mc-code is split: +\RequirePackage { tagpdf-mc-code-shared } +\bool_if:NTF \g_@@_mode_lua_bool + { + \RequirePackage {tagpdf-mc-code-lua} + } + { + \RequirePackage { tagpdf-mc-code-generic } % + } + +\RequirePackage { tagpdf-struct-code } +\RequirePackage { tagpdf-space-code } +%</package> +% \end{macrocode} +% +% \begin{macrocode} +%<*user> +\ProvidesExplPackage {tagpdf-user} {2021/02/23} {0.80} + {tagpdf - user commands} + +\NewDocumentCommand \tagpdfsetup { m } + { + \keys_set:nn { @@ / setup } { #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 + +%%% stop tagging +\bool_new:N \l_@@_stop_bool + +\prg_new_conditional:Nnn \@@_if_stop: {p,T,F,TF} + { + \bool_if:NTF \l_@@_stop_bool + { \prg_return_true: } + { \prg_return_false: } + } + +\prg_new_eq_conditional:NNn \tag_if_stop: \@@_if_stop: {p,T,F,TF} + +\cs_new_protected:Npn \@@_stop: + { + \bool_set_true:N \l_@@_stop_bool + \cs_set_eq:NN \tag_mc_begin:n \use_none:n + \cs_set_eq:NN \tag_mc_end: \prg_do_nothing: + \cs_set_eq:NN \tag_mc_use:n \use_none:n + \cs_set_eq:NN \tag_struct_begin:n \use_none:n + \cs_set_eq:NN \tag_struct_end: \prg_do_nothing: + \cs_set_eq:NN \tag_struct_use:n \use_none:n + %deprecated + \cs_set_eq:NN \uftag_mc_begin:n \tag_mc_begin:n + \cs_set_eq:NN \uftag_mc_end: \tag_mc_end: + \cs_set_eq:NN \uftag_mc_use:n \tag_mc_use:n + \cs_set_eq:NN \uftag_struct_begin:n \tag_struct_begin:n + \cs_set_eq:NN \uftag_struct_end: \tag_struct_end: + \cs_set_eq:NN \uftag_struct_use:n \tag_struct_use:n + } + +\cs_new_protected:Npn \tag_stop_group_begin: + { + \group_begin: + \@@_stop: + } + +\cs_set_eq:NN \tag_stop_group_end: \group_end: + + +%%% a generic command to retrieve data + +\cs_new:Npn \tagpdfget #1 { \use:c {@@_get_data_#1: } } +\cs_new:Npn \tag_get:n #1 { \use:c {@@_get_data_#1: } } +%deprecated: +\cs_new:Npn \uftag_get:n #1 { \use:c {@@_get_data_#1: } } + + +%%%% mc related user commands +\NewDocumentCommand \tagmcifinTF { m m } + { + \@@_mc_if_in:TF { #1 } { #2 } + } + + +\NewDocumentEnvironment{tagmcartifact}{m} + { + \tag_mc_artifact_group_begin:n { #1}\ignorespaces + } + { + \tag_mc_artifact_group_end: + } + +\NewDocumentCommand \tagmcbegin { m } + { + \tag_mc_begin:n {#1}\ignorespaces + } + + +\NewDocumentCommand \tagmcend { } + { + \unskip % this unskip appears to mess up some spacing; can we do this in another way? + \tag_mc_end: + } + +\NewDocumentCommand \tagmcuse { m } + { + \tag_mc_use:n {#1} + } + + +%%%% structure related commands + +\NewDocumentCommand \tagstructbegin { m } + { + \tag_struct_begin:n {#1} + } + +\NewDocumentCommand \tagstructend { } + { + \tag_struct_end: + } + +\NewDocumentCommand \tagstructuse { m } + { + \tag_struct_use:n {#1} + } + + + +%%%% debug/show commands +\NewDocumentCommand\showtagpdfmcdata { O {\@@_tag_get_mc_abs_cnt:} } + { + \bool_if:NT \g_@@_mode_lua_bool + { + \sys_if_engine_luatex:T + { + \directlua{ltx.@@.trace.show_all_mc_data(#1)} + } + } + } + +\NewDocumentCommand\showtagpdfattributes { } + { + \bool_if:NT \g_@@_mode_lua_bool + { + \sys_if_engine_luatex:T + { + \directlua + { + ltx.@@.trace.log + ( + "showtagpdfattributes: + MC=>abscnt=\@@_get_mc_abs_cnt: + =>attr=\the\l_@@_mc_cnt_attr=>tag=" + .. + tostring(ltx.@@.func.get_tag_from (\the\l_@@_mc_type_attr)) + .. + "=\the\l_@@_mc_type_attr",0 + ) + } + \ignorespaces + } + } + } + +\sys_if_engine_luatex:T + { + \NewDocumentCommand\pdffakespace { } + { + \@@_fakespace: + } + } + +%</user> +% \end{macrocode} +% +% \begin{macrocode} +%<*deprecated> +% \uftag_get:n +% \uftag_mc_if_in: +% \uftag_mc_begin:n +% \uftag_mc_end: +% \uftag_mc_use:n +% \uftag_struct_begin:n +% \uftag_struct_end: +% \uftag_finish_structure: +%</deprecated> +% \end{macrocode} |