[latex3-commits] [git/LaTeX3-latex3-latex2e] shipout-hook-adjust: reordered the execution of shipout hooks so that code in shipout/firstpage really executes first (3db2fc51)
Frank Mittelbach
frank.mittelbach at latex-project.org
Tue Jan 19 12:58:54 CET 2021
Repository : https://github.com/latex3/latex2e
On branch : shipout-hook-adjust
Link : https://github.com/latex3/latex2e/commit/3db2fc51aac8eab2f75f18a65c05b1e2372589d2
>---------------------------------------------------------------
commit 3db2fc51aac8eab2f75f18a65c05b1e2372589d2
Author: Frank Mittelbach <frank.mittelbach at latex-project.org>
Date: Tue Jan 19 12:58:54 2021 +0100
reordered the execution of shipout hooks so that code in shipout/firstpage really executes first
>---------------------------------------------------------------
3db2fc51aac8eab2f75f18a65c05b1e2372589d2
base/changes.txt | 5 ++
base/ltshipout.dtx | 135 ++++++++++++++++++++++++-------
base/testfiles-lthooks2/shipout2-016.lvt | 32 ++++++++
base/testfiles-lthooks2/shipout2-016.tlg | 71 ++++++++++++++++
4 files changed, 213 insertions(+), 30 deletions(-)
diff --git a/base/changes.txt b/base/changes.txt
index 2f6834b4..32b162ef 100644
--- a/base/changes.txt
+++ b/base/changes.txt
@@ -6,6 +6,11 @@ completeness or accuracy and it contains some references to files that
are not part of the distribution.
================================================================================
+2021-01-19 Frank Mittelbach <Frank.Mittelbach at latex-project.org>
+
+ * ltshipout.dtx: Reordered execution of shipout hooks so that code
+ in one can influence code in later ones in a more natural manner.
+
2021-01-12 Frank Mittelbach <Frank.Mittelbach at latex-project.org>
* ltshipout.dtx: Make sure that the shipout/firstpage hook material
diff --git a/base/ltshipout.dtx b/base/ltshipout.dtx
index 5dd75bf5..a0d7de0e 100644
--- a/base/ltshipout.dtx
+++ b/base/ltshipout.dtx
@@ -32,8 +32,8 @@
%%% From File: ltshipout.dtx
%
% \begin{macrocode}
-\providecommand\ltshipoutversion{v1.0g}
-\providecommand\ltshipoutdate{2021/01/18}
+\providecommand\ltshipoutversion{v1.0h}
+\providecommand\ltshipoutdate{2021/01/19}
% \end{macrocode}
%
%<*driver>
@@ -899,6 +899,15 @@
% \begin{macrocode}
\@@_get_box_size:N #1
% \end{macrocode}
+% The first hook we run is the \hook{shipout/firstpage} hook. This
+% is only done once, then the \cs{@@_run_firstpage_hook:}
+% command redefines itself to do nothing. If the hook contains
+% \cs{special}s for integration at the top of the page they will be
+% temporarily stored in a safe place and added later with
+% \cs{@@_add_firstpage_specials:}.
+% \begin{macrocode}
+ \@@_run_firstpage_hook:
+% \end{macrocode}
% Run the hooks for background and foreground or, if this
% is called by \cs{RawShipout}, copy the box \cs{l_@@_raw_box} to
% \cs{l_shipout_box} so that firstpage and lastpage material gets
@@ -906,12 +915,12 @@
% \begin{macrocode}
#3
% \end{macrocode}
-% We then run \cs{@@_add_firstpage_hook:} that adds
+% We then run \cs{@@_add_firstpage_specials:} that adds
% the content of the hook \hook{shipout/firstpage} to the
% start of the first page (if non-empty). It is then redefined to
% do nothing on later pages.
% \begin{macrocode}
- \@@_add_firstpage_hook:
+ \@@_add_firstpage_specials:
% \end{macrocode}
% Then we check if we have to add the \hook{shipout/lastpage} hook
% or the corresponding kernel hook
@@ -946,7 +955,7 @@
% \cs{l_shipout_box} to its earlier state if that is necessary. On
% later pages this is then a no-op.
% \begin{macrocode}
- \@@_drop_firstpage_hook:
+ \@@_drop_firstpage_specials:
% \end{macrocode}
% The \hook{shipout/after} hook (if in \verb=#4=) needs to run with
% \cs{protect}ed commands again being executed, because that hook
@@ -1052,36 +1061,47 @@
% \end{macro}
%
%
-% \begin{macro}{\@@_add_firstpage_hook:,\@@_drop_firstpage_hook}
+% \begin{macro}{\@@_run_firstpage_hook:}
+%
+% There are three commands to handle the \hook{shipout/firstpage}
+% hook:
+% \cs{@@_run_firstpage_hook:}, \cs{@@_add_firstpage_specials:} and
+% \cs{@@_drop_firstpage_hook}.
%
-% This command adds any specials into a box and adds that to the
-% very beginning of the first box shipped out. After that we
-% redefine it to do nothing on later pages.
+% That hook is supposed to contain \cs{special}s and similar
+% material to be placed at the very beginning of the output page
+% and so it needs careful placing to avoid that anything else gets
+% in front of it. And this means we have to wait with this until
+% other hooks such as \hook{shipout/background} have added their
+% bits. It is also important that such \cs{special}s show up only
+% on the very first page, so if this page gets saved before
+% \cs{shipout} for later reuse, we have to make sure that they
+% aren't in the saved version.
+%
+% In addition the hook may also contain code to be executed ``first'', e.g.,
+% visible from code in \hook{shipout/background} and this conflicts
+% with adding the \cs{special}s late.
+%
+% Therefore the processing is split into different parts:
+% \cs{@@_run_firstpage_hook:} is done early and checks if there is
+% any material in the hook.
% \begin{macrocode}
-\cs_new:Npn \@@_add_firstpage_hook: {
+\cs_new:Npn \@@_run_firstpage_hook: {
+ \hook_if_empty:nTF {shipout/firstpage}
% \end{macrocode}
-% Adding something to the beginning means adding it to the
-% background as that layer is done first in the output. Of course
-% that is only needed if the hook actually contains anything.
+% If not then we define the other two commands to do nothing.
% \begin{macrocode}
- \hook_if_empty:nF {shipout/firstpage}
{
+ \cs_gset_eq:NN \@@_add_firstpage_specials: \prg_do_nothing:
+ \cs_gset_eq:NN \@@_drop_firstpage_specials: \prg_do_nothing:
+ }
% \end{macrocode}
-% First we make a copy of the \cs{l_shipout_box} that we can
-% restore it later on.
+% If there is material we execute inside a box, which means any
+% \cs{special} will end up in that box and any other code is
+% executed and can have side effects (as long as they are global).
% \begin{macrocode}
- \box_set_eq:NN \l_@@_raw_box \l_shipout_box
- \@@_add_background_box:n { \UseHook{shipout/firstpage} }
-% \end{macrocode}
-% After the actual shipout \cs{@@_drop_firstpage_hook:} is
-% run. Normally that does nothing but now it is used (once) to
-% restore the earlier content of \cs{l_shipout_box} and then
-% redefines itself again to do nothing.
-% \begin{macrocode}
- \cs_gset:Npn \@@_drop_firstpage_hook: {
- \box_set_eq:NN \l_shipout_box \l_@@_raw_box
- \cs_gset_eq:NN \@@_drop_firstpage_hook: \prg_do_nothing:
- }
+ {
+ \hbox_set:Nn \l_@@_firstpage_box { \UseHook{shipout/firstpage} }
}
% \end{macrocode}
% Once we are here we change the definition to do nothing next time
@@ -1089,7 +1109,7 @@
% to become a warning and not add further material to a hook that
% is never used again.
% \begin{macrocode}
- \cs_gset_eq:NN \@@_add_firstpage_hook: \prg_do_nothing:
+ \cs_gset_eq:NN \@@_run_firstpage_hook: \prg_do_nothing:
\cs_gset:Npn \@@_add_firstpage_material:Nn ##1 ##2 {
\@latex at warning{
First~ page~ is~ already~ shipped~ out,~ ignoring\MessageBreak
@@ -1097,12 +1117,67 @@
}
}
% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_add_firstpage_specials:,\@@_drop_firstpage_hook}
+% The \cs{@@_add_firstpage_specials:} then adds the \cs{special}s
+% stored in \cs{l_@@_firstpage_box} to the page to be shipped out
+% when the time is ready. Note that if there was no material in the
+% \hook{shipout/firstpage} hook then this command gets redefined to
+% do nothing. But for most documents there is something, e.g., some
+% PostScript header, or some meta data declaration, etc.\ so by
+% default we assume there is something to do.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_firstpage_specials: {
+% \end{macrocode}
+% First we make a copy of the \cs{l_shipout_box} that we can
+% restore it later on.
+% \begin{macrocode}
+ \box_set_eq:NN \l_@@_raw_box \l_shipout_box
+% \end{macrocode}
+% Adding something to the beginning means adding it to the
+% background as that layer is done first in the output.
+% \begin{macrocode}
+ \@@_add_background_box:n { \hbox_unpack:N \l_@@_firstpage_box }
+% \end{macrocode}
+% After the actual shipout \cs{@@_drop_firstpage_specials:} is
+% run to
+% restore the earlier content of \cs{l_shipout_box} and then
+% redefines itself again to do nothing.
+%
+% As a final act we change the definition to do nothing next time.
+% \begin{macrocode}
+ \cs_gset_eq:NN \@@_add_firstpage_specials: \prg_do_nothing:
+}
+% \end{macrocode}
%
+% The \cs{@@_drop_firstpage_specials:} is run after the shipout has
+% accured but before the \hook{shipout/afterpage} hook is executed.
+% That is the point where we have to restore the \cs{ShipoutBox} to
+% its state without the \hook{shipout/firstpage} material.
% \begin{macrocode}
-\cs_new_eq:NN \@@_drop_firstpage_hook: \prg_do_nothing:
+\cs_new:Npn \@@_drop_firstpage_specials: {
+ \box_set_eq:NN \l_shipout_box \l_@@_raw_box
+% \end{macrocode}
+% If there was no such material then \cs{@@_run_firstpage_hook:}
+% will have changed the definition to a no-op already. Otherwise
+% this is what we do here.
+% \begin{macrocode}
+ \cs_gset_eq:NN \@@_drop_firstpage_specials: \prg_do_nothing:
+ }
% \end{macrocode}
% \end{macro}
%
+
+% \begin{macro}{\l_@@_firstpage_box}
+% The box to hold any firstpage \cs{special}s.
+% \begin{macrocode}
+\box_new:N \l_@@_firstpage_box
+% \end{macrocode}
+% \end{macro}
+
%
% \begin{macro}{\g_@@_lastpage_handled_bool}
% A boolean to signal if we have already handled the
diff --git a/base/testfiles-lthooks2/shipout2-016.lvt b/base/testfiles-lthooks2/shipout2-016.lvt
new file mode 100644
index 00000000..0f6971a0
--- /dev/null
+++ b/base/testfiles-lthooks2/shipout2-016.lvt
@@ -0,0 +1,32 @@
+\RequirePackage[enable-debug]{expl3}
+\ExplSyntaxOn
+\debug_on:n { check-declarations , deprecation }
+\ExplSyntaxOff
+
+\documentclass[a4paper]{article}
+
+\input{regression-test}
+
+\AddToHook{shipout/foreground}{\show\foreground}
+\AddToHook{shipout/background}{\show\background}
+\AddToHook{shipout/firstpage}{\show\firstpage}
+\makeatletter
+\g at addto@macro \@kernel at after@shipout at background
+ {\show\kernel}
+\AddToHook{shipout/lastpage}{\show\lastpage}
+
+\DebugShipoutsOn
+
+\showoutput
+
+
+\begin{document}
+
+\START
+
+blub
+
+\end{document}
+
+
+
diff --git a/base/testfiles-lthooks2/shipout2-016.tlg b/base/testfiles-lthooks2/shipout2-016.tlg
new file mode 100644
index 00000000..65836000
--- /dev/null
+++ b/base/testfiles-lthooks2/shipout2-016.tlg
@@ -0,0 +1,71 @@
+This is a generated file for the l3build validation system.
+Don't change this file in any respect.
+Absolute page = 1 (target: 1)
+> \firstpage=undefined.
+\__hook_toplevel shipout/firstpage ... \firstpage
+l. ...\end{document}
+> \foreground=undefined.
+\__hook_toplevel shipout/foreground ...foreground
+l. ...\end{document}
+> \background=undefined.
+\__hook_toplevel shipout/background ...background
+l. ...\end{document}
+> \kernel=undefined.
+\@kernel at after@shipout at background ->\show \kernel
+l. ...\end{document}
+Executing lastpage hook on page 1
+> \lastpage=undefined.
+\__hook_toplevel shipout/lastpage ...ow \lastpage
+l. ...\end{document}
+Completed box being shipped out [1]
+\vbox(682.0+0.0)x398.0
+.\hbox(0.0+0.0)x0.0
+.\hbox(0.0+0.0)x0.0
+..\kern -72.27
+..\vbox(0.0+0.0)x0.0, glue set 72.27fil
+...\kern -72.27
+...\hbox(0.0+0.0)x0.0
+....\glue 0.0 plus 1.0fil minus 1.0fil
+...\glue 0.0 plus 1.0fil minus 1.0fil
+.\glue 17.0
+.\vbox(665.0+0.0)x345.0, shifted 53.0
+..\vbox(12.0+0.0)x345.0, glue set 12.0fil
+...\glue 0.0 plus 1.0fil
+...\hbox(0.0+0.0)x345.0
+..\glue 25.0
+..\glue(\lineskip) 0.0
+..\vbox(598.0+0.0)x345.0, glue set 587.9372fil
+...\write-{}
+...\glue(\topskip) 3.05556
+...\hbox(6.94444+0.0)x345.0, glue set 310.5555fil
+....\hbox(0.0+0.0)x15.0
+....\OT1/cmr/m/n/10 b
+....\OT1/cmr/m/n/10 l
+....\OT1/cmr/m/n/10 u
+....\OT1/cmr/m/n/10 b
+....\penalty 10000
+....\glue(\parfillskip) 0.0 plus 1.0fil
+....\glue(\rightskip) 0.0
+...\glue 0.0 plus 1.0fil
+...\glue 0.0
+...\glue 0.0 plus 0.0001fil
+..\glue(\baselineskip) 23.55556
+..\hbox(6.44444+0.0)x345.0, glue set 170.0fil
+...\glue 0.0 plus 1.0fil
+...\OT1/cmr/m/n/10 1
+...\glue 0.0 plus 1.0fil
+.\kern -682.0
+.\hbox(0.0+0.0)x0.0
+..\kern -72.27
+..\vbox(0.0+0.0)x0.0, glue set 72.27fil
+...\kern -72.27
+...\hbox(0.0+0.0)x0.0
+....\glue 0.0 plus 1.0fil minus 1.0fil
+...\glue 0.0 plus 1.0fil minus 1.0fil
+.\kern 682.0
+.\kern 0.0
+.\kern 0.0
+.\kern -682.0
+.\hbox(0.0+0.0)x0.0
+.\kern 682.0
+(shipout2-016.aux)
More information about the latex3-commits
mailing list.