summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx')
-rw-r--r--Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx498
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}