diff options
Diffstat (limited to 'macros/latex-dev/required/latex-lab/latex-lab-float.dtx')
-rw-r--r-- | macros/latex-dev/required/latex-lab/latex-lab-float.dtx | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/macros/latex-dev/required/latex-lab/latex-lab-float.dtx b/macros/latex-dev/required/latex-lab/latex-lab-float.dtx new file mode 100644 index 0000000000..ed8b8390e2 --- /dev/null +++ b/macros/latex-dev/required/latex-lab/latex-lab-float.dtx @@ -0,0 +1,492 @@ +% \iffalse meta-comment +% +%% File: latex-lab-float.dtx (C) Copyright 2023 LaTeX Project +% +% 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 +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-float.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \textsf{latex-lab-floats} package\\ +% Tagging of floats } +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{v0.8 2023-05-17} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% \begin{documentation} +% \begin{abstract} +% The following code implements a first draft for the tagging of float +% environments +% \end{abstract} +% +% +% \section{Introduction} +% +% The code here handle the tagging of float environments. +% +% Figures (and tables) are in \LaTeX{} typically typeset in float environments. +% These are boxes which can \emph{float} away to special float areas on the pages, +% e.g., to the top or the bottom of a page or to special float pages. +% If the rules allow it they can also be placed in the main text stream (\enquote{here}). +% Floats can also be collected at the end of the document. +% In either case the order within each type of floats +% (e.g., figures, tables, algorithms, etc.) is preserved. +% +% A special type, called a H-float, (provided by the float package) +% is always placed in the main text stream and does not +% necessarly preserve the order with normal floats of the same type: It is basically +% a minipage with a caption. +% +% Floats typically contain a figure (or a table, etc.) and a caption, +% but more complex constructions with subfigures, +% copyright statements, sources or additional description are possible too. +% +% In the \LaTeX{} source a float is normally more or less at the place of +% the first call-out, but when preparing a document for print the code +% is sometimes moved to place floats in a more visually pleasing way. +% +% \section{Tagging} +% +% Floats (with the exception of H-floats) do not belong into the text stream, they +% are \enquote{consultation objects}: Readers must be able to choose if and when they read the float. +% Floats have captions, the PDF rules require that a \texttt{Caption} is the first or last +% structure in its parent structure. +% This poses some challenges on a good tagging. +% +% In PDF~2.0 there is the suitable \texttt{Aside} tag which hopefully will +% be handled correctly regarding the reading order once processor actually support +% PDF~2.0. But in PDF~1.7 we rolemap it to \texttt{Note} and this doesn't lead to +% a good reading order. The code therefore collect the float structures and moves +% them to a \texttt{Sect} the end of the document or the chapter +% (H-floats once they are handled will not be moved). +% +% To fulfill the requirement that a \texttt{Caption} should be at the begin or end, we always +% move it to the begin of the structure. If a float has two captions the author +% has to insert a command which splits the float in two. +% +% Subfigures and subcaptions are currently not handled, but will be implemented +% as simple \texttt{Part} with their own \texttt{Caption}. +% +% \section{Links} +% The code disable the caption patches from hyperref. It will add an anchor at the +% begin of the float or a split. It changes caption so that a link to a caption label +% will go to the begin of the float. +% +% \section{Tools} +% +% The code add two keys for the \cs{tagtool} command +% +% \begin{description} +% \item[flush-floats] This will flush out the collected floats sofar (currently +% table and figure. The value is a sectioning level, e.g. \texttt{section} or \texttt{chapter}, +% the floats will then inserted as a \texttt{Sect} of this level (all \texttt{Sect} of smaller or equal +% level are closed). The key then starts a new container for following floats. +% If no value is given, the \texttt{Sect} is at the document level. The code automatically +% flush all open floats at the end of the document. +% +% \item[split-float] This can be used inside a float if there are two captions. +% It will only work reasonably well if the content of the float parts are in a sensible order +% and can be separated by this command. More complex setups with tabulars will need more +% thoughts +% +% \end{description} +% +% +% \begin{macrocode} +%<@@=tag> +%<*package> +% \end{macrocode} +% \end{documentation} +% \begin{implementation} +% \section{Implementation} +% \begin{macrocode} +\ProvidesExplPackage {latex-lab-testphase-float} {2023-04-28} {0.8} + {Code related to the tagging of floats} +% \end{macrocode} +% \subsection{Variables} +% We rolemap to Aside, and float sections to Sect +% +% \begin{macrocode} +\tagpdfsetup{add-new-tag=float/Aside} +\tagpdfsetup{add-new-tag=figures/Sect} +\tagpdfsetup{add-new-tag=tables/Sect} +% \end{macrocode} +% +% \begin{variable}{ +% \g_@@_float_sect_prop, +% \g_@@_float_types_seq +% } +% These variables will hold the structure number for the float container +% and the list of float types. Currently only figure and table are supported +% TODO: interface to declare new float types. +% \begin{macrocode} +\prop_new:N \g_@@_float_sect_prop +\seq_new:N \g_@@_float_types_seq +\seq_gput_right:Nn \g_@@_float_types_seq {figure} +\seq_gput_right:Nn \g_@@_float_types_seq {table} +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\g_@@_float_sect_bool} +% With this boolean float collection is switched on and off. +% Currently it is always on and set globally. +% TODO: think if an interface is needed. +% TODO: would a local variable make more sense? +% \begin{macrocode} +\bool_new:N \g_@@_float_sect_bool +\bool_gset_true:N \g_@@_float_sect_bool +% \end{macrocode} +% \end{variable} +% +% +%\subsection{Moving float structures} +% +% Currently it is for all float types or none. +% Probably we will need some more options here to select some float types. +% +% \begin{macro}{\@@_float_init_collect:} +% This initializes a container structure for every float type. +% It can be used more than once in a document, this allows to have e.g. +% chapter wise containers. +% \begin{macrocode} +\cs_new_protected:Npn\@@_float_init_collect: + { + \bool_if:NT\g_@@_float_sect_bool + { + \seq_map_inline:Nn\g_@@_float_types_seq + { + \tag_struct_begin:n{tag=##1s,stash} + \prop_gput:Nnx\g_@@_float_sect_prop {##1-struct}{\int_use:N\c@g__tag_struct_abs_int} + \tag_struct_end: + } + } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_float_stop_sect:} +% This pushes out the floats. For every type is checks if there is actually +% a float of this type and then writes out the container structure. +% \begin{macrocode} +\cs_new_protected:Npn \@@_float_stop_sect: + { + \bool_if:NT\g_@@_float_sect_bool + { + \seq_map_inline:Nn\g_@@_float_types_seq + { + \prop_get:NnNT\g_@@_float_sect_prop{##1-used}\l_@@_tmpa_tl + { + \exp_args:Ne + \tag_struct_use_num:n{\prop_item:Nn\g_@@_float_sect_prop{##1-struct}} + \prop_gremove:Nn \g_@@_float_sect_prop{##1-used} + } + } + } + } +% \end{macrocode} +% \end{macro} + +% \begin{macro}{flush-floats} +% This is a key for \cs{tagtool} to flush out the collected floats. +% The value allows to set to which level the create Sect contains. +% So \texttt{section} will close all previous Sect until the section level +% and create a new section. +% \begin{macrocode} +\keys_define:nn { tag / tool} + { + flush-floats .code:n = + { + \keys_set:nn {tag / tool} {sec-stop=#1} + \@@_float_stop_sect: + \@@_float_init_collect: + }, + flush-float .default:n = Document + } +% \end{macrocode} +% \end{macro} +% We need at least one pair +% \begin{macrocode} +\AddToHook{begindocument/end}[latex-lab/float] + {\@@_float_init_collect:} +\AddToHook{tagpdf/finish/before}[latex-lab/float] + {\par\__tag_sec_end:n{-10}\@@_float_stop_sect:} +\DeclareHookRule{tagpdf/finish/before}{latex-lab/float}{before}{tagpdf} +% \end{macrocode} +% \subsection{Splitting floats} +% \begin{macro}{split-float} +% TODO: check if the target affect spacing!! +% \begin{macrocode} +\keys_define:nn { tag / tool} + { + split-float .code:n = + { + \@@_float_end: + \@@_float_begin: + \MakeLinkTarget[tagstructure]{g__tag_struct_abs_int} + } + } +% \end{macrocode} +% \end{macro} + +% \subsection{Patching} +% \begin{macro}{\@@_float_stop_par:,\@@_float_start_par:} +% if a float is in a par, we need commands to stop and restart the P-mc +% \begin{macrocode} +\cs_new_protected:Npn \@@_float_stop_par: + { + \tag_mc_end: + \bool_if:NF \g_@@_float_sect_bool + { + \tag_struct_end: + } + } +\cs_new_protected:Npn \@@_float_start_par: + { + \bool_if:NF \g_@@_float_sect_bool + { + \tag_struct_begin:n{tag=text}% + } + \tag_mc_begin:n{tag=P} + } + +% \end{macrocode} +% \end{macro} +% These commands are the main commands to start and end the float tagging. +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_float_begin: + {% +% \end{macrocode} +% We test if the float structure should be included directly or move to a dedicated section. +% \begin{macrocode} + \bool_if:NTF\g_@@_float_sect_bool + { + \exp_args:Ne + \tag_struct_begin:n{tag=float,parent=0\prop_item:No\g_@@_float_sect_prop{\@captype-struct}}% + \prop_gput:Nxx \g_@@_float_sect_prop {\@captype-used}{true} + } + { + \tag_struct_begin:n{tag=float} + } + \tl_set:Nx\@current@float@struct{\tag_get:n{struct_num}}% + \typeout{Float structure: \@current@float@struct} + } + +\cs_new_protected:Npn\@@_float_end:{\tag_struct_end:} %end Aside + +% \end{macrocode} +% This patches the main command \cs{@xfloat}. +% There is a : in the code, so we disable expl3 syntax +% \begin{macrocode} +\ExplSyntaxOff +\def\@xfloat #1[#2]{% + \@nodocument + \def \@captype {#1}% + \def \@fps {#2}% + \@onelevel@sanitize \@fps + \def \reserved@b {!}% + \ifx \reserved@b \@fps + \@fpsadddefault + \else + \ifx \@fps \@empty + \@fpsadddefault + \fi + \fi + \ifhmode + \@bsphack +% \end{macrocode} +% If the float is in hmode we have to interrupt the P +% \begin{macrocode} + \@nameuse{@@_float_stoppar:} %<---end P + \@floatpenalty -\@Mii + \else + \@floatpenalty-\@Miii + \fi + \ifinner + \@parmoderr\@floatpenalty\z@ + \else + \@next\@currbox\@freelist + {% + \@tempcnta \sixt@@@@n + \expandafter \@tfor \expandafter \reserved@a + \expandafter :\expandafter =\@fps + \do + {% + \if \reserved@a h% + \ifodd \@tempcnta + \else + \advance \@tempcnta \@ne + \fi + \else\if \reserved@a t% + \@setfpsbit \tw@ + \else\if \reserved@a b% + \@setfpsbit 4% + \else\if \reserved@a p% + \@setfpsbit 8% + \else\if \reserved@a !% + \ifnum \@tempcnta>15 + \advance\@tempcnta -\sixt@@@@n\relax + \fi + \else + \@latex@error{Unknown float option `\reserved@a'}% + {Option `\reserved@a' ignored and `p' used.}% + \@setfpsbit 8% + \fi\fi\fi\fi\fi + }% + \@tempcntb \csname ftype@\@captype \endcsname + \multiply \@tempcntb \@xxxii + \advance \@tempcnta \@tempcntb + \global \count\@currbox \@tempcnta + }% + \@fltovf + \fi +% \end{macrocode} +% This starts the structure for the float. +% \begin{macrocode} + \@nameuse{@@_float_begin:}% + \global \setbox\@currbox + \color@vbox + \normalcolor + \vbox \bgroup + \hsize\columnwidth + \@parboxrestore + \@floatboxreset +% \end{macrocode} +% We add a target for links. TODO: check that it doesn't affect spacing!! +% \begin{macrocode} + \MakeLinkTarget[tagstructure]{g__tag_struct_abs_int}% +}% +% \end{macrocode} +% The end code of the float ... +% \begin{macrocode} +\def\end@float{% + \@endfloatbox + \@nameuse{@@_float_end:}% + \ifnum\@floatpenalty <\z@ + \@largefloatcheck + \@cons\@currlist\@currbox + \ifnum\@floatpenalty <-\@Mii + \penalty -\@Miv + \@tempdima\prevdepth + \vbox{}% + \prevdepth\@tempdima + \penalty\@floatpenalty + \else + \vadjust{\penalty -\@Miv \vbox{}\penalty\@floatpenalty}\@Esphack + \@nameuse{@@_float_start_par:} %restart P safe here?? + \fi + \fi +} +\ExplSyntaxOn +% \end{macrocode} +% +% \subsection{Handling captions} +% +% To avoid that hyperref interferes we disable its patches: +% \begin{macrocode} +\def\hyper@nopatch@caption{} +% \end{macrocode} +% As we will use the structure number in the target, we need to provide a +% theH-representation. (Once the kernel will create +% theH-representation generally this will be provided automatically, as tagpdf uses +% \cs{newcounter}) +% \begin{macrocode} +\providecommand\theHg__tag_struct_abs_int{\int_use:N\c@g__tag_struct_abs_int} +% \end{macrocode} + +% \begin{macro}{\@makecaption} +% \cs{@makecaption} is defined by the classes so we overwrite it for now +% at begin document. +% \begin{macrocode} +\AddToHook{begindocument} + { + \long\def\@makecaption#1#2{% + \vskip\abovecaptionskip + \xdef\@currentHref{tagstructure.\@current@float@struct}% +% \end{macrocode} +% we don't want tagging when storing the caption for the singleline check +% \begin{macrocode} + \tag_stop:n{caption} + \sbox\@tempboxa{#1:~#2}% + \tag_start:n{caption} +% \end{macrocode} +% we stop paratagging. TODO: check +% \begin{macrocode} + \tagtool{para=false} + \tag_struct_begin:n{tag=Caption,parent=\@current@float@struct} +% \end{macrocode} +% move the caption to the begin of the float structure: +% \begin{macrocode} + \seq_gpop_right:cN {g__tag_struct_kids_\@current@float@struct _seq}\l_@@_tmpa_tl + \seq_gput_left:cV {g__tag_struct_kids_\@current@float@struct _seq}\l_@@_tmpa_tl + \ifdim \wd\@tempboxa >\hsize + \tag_struct_begin:n{tag=Lbl} + \tag_mc_begin:n{} + #1:~ + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin:n{} + #2\par + \tag_mc_end: + \else +% \end{macrocode} +% we don't reuse the box as it doesn't contain tagging, but set the text explicitly. +% \begin{macrocode} + \global \@minipagefalse + \hb@xt@\hsize{\hfil + \tag_struct_begin:n{tag=Lbl} + \tag_mc_begin:n{} + #1:~ + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin:n{} + #2\par + \tag_mc_end:\hfil}% + \fi + \tag_struct_end: %caption + \vskip\belowcaptionskip} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} + +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{float-latex-lab-testphase.ltx} + [2023-04-30 v0.8 code related to the tagging of floats] +\RequirePackage{latex-lab-testphase-float} +%</latex-lab> +% \end{macrocode} +% \end{implementation} |