texlive[74575] Master/texmf-dist: l3backend-dev (11mar25)

commits+karl at tug.org commits+karl at tug.org
Tue Mar 11 21:09:53 CET 2025


Revision: 74575
          https://tug.org/svn/texlive?view=revision&revision=74575
Author:   karl
Date:     2025-03-11 21:09:53 +0100 (Tue, 11 Mar 2025)
Log Message:
-----------
l3backend-dev (11mar25)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex-dev/l3backend/CHANGELOG.md
    trunk/Master/texmf-dist/doc/latex-dev/l3backend/README.md
    trunk/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.tex
    trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-basics.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-box.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-color.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-draw.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-header.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-opacity.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdf.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend.ins
    trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvipdfmx.def
    trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.def
    trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.pro
    trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvisvgm.def
    trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.def
    trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.lua
    trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-pdftex.def
    trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-xetex.def

Added Paths:
-----------
    trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdfannot.dtx

Modified: trunk/Master/texmf-dist/doc/latex-dev/l3backend/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3backend/CHANGELOG.md	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3backend/CHANGELOG.md	2025-03-11 20:09:53 UTC (rev 74575)
@@ -6,6 +6,14 @@
 
 ## [Unreleased]
 
+## [2025-03-10]
+
+### Added
+- Support for canvas shifts
+
+### Changed
+- Move PDF annotation functions to `pdfannot` module
+
 ## [2024-05-08]
 
 ### Changed
@@ -355,7 +363,8 @@
 - Include `l3backend` in file names
 - Moved backend code to internal for each 'parent' module
 
-[Unreleased]: https://github.com/latex3/latex3/compare/2024-05-08...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2025-03-10...HEAD
+[2025-03-10]: https://github.com/latex3/latex3/compare/2024-05-08...2025-03-10
 [2024-05-08]: https://github.com/latex3/latex3/compare/2024-04-11...2024-05-08
 [2024-04-11]: https://github.com/latex3/latex3/compare/2024-03-14...2024-04-11
 [2024-03-14]: https://github.com/latex3/latex3/compare/2024-02-20...2024-03-14

Modified: trunk/Master/texmf-dist/doc/latex-dev/l3backend/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3backend/README.md	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3backend/README.md	2025-03-11 20:09:53 UTC (rev 74575)
@@ -1,7 +1,7 @@
 LaTeX3 Backend Drivers
 ======================
 
-Release 2024-05-08
+Release 2025-03-10
 
 This package forms parts of `expl3`, and contains the code used to interface
 with backends (drivers) across the `expl3` codebase. The functions here are
@@ -11,6 +11,6 @@
 
 -----
 
-<p>Copyright (C) 2019-2024 The LaTeX Project <br />
+<p>Copyright (C) 2019-2025 The LaTeX Project <br />
 <a href="http://latex-project.org/">http://latex-project.org/</a> <br />
 All rights reserved.</p>

Modified: trunk/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.tex	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.tex	2025-03-11 20:09:53 UTC (rev 74575)
@@ -2,7 +2,7 @@
 
 File: l3backend-code.tex
 
-Copyright (C) 2019,2021 The LaTeX Project
+Copyright (C) 2019,2021,2025 The 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
@@ -44,6 +44,7 @@
     l3backend-draw.dtx     ,
     l3backend-graphics.dtx ,
     l3backend-pdf.dtx      ,
+    l3backend-pdfannot.dtx ,
     l3backend-opacity.dtx  ,
     l3backend-header.dtx
   }

Modified: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-basics.dtx	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-basics.dtx	2025-03-11 20:09:53 UTC (rev 74575)
@@ -2,7 +2,7 @@
 %
 %% File: l3backend-basics.dtx
 %
-% Copyright (C) 2019-2024 The LaTeX Project
+% Copyright (C) 2019-2025 The 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
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2024-05-08}
+% \date{Released 2025-03-10}
 %
 % \maketitle
 %
@@ -70,27 +70,27 @@
 %    \begin{macrocode}
 \ProvidesExplFile
 %<*dvipdfmx>
-  {l3backend-dvipdfmx.def}{2024-05-08}{}
+  {l3backend-dvipdfmx.def}{2025-03-10}{}
   {L3 backend support: dvipdfmx}
 %</dvipdfmx>
 %<*dvips>
-  {l3backend-dvips.def}{2024-05-08}{}
+  {l3backend-dvips.def}{2025-03-10}{}
   {L3 backend support: dvips}
 %</dvips>
 %<*dvisvgm>
-  {l3backend-dvisvgm.def}{2024-05-08}{}
+  {l3backend-dvisvgm.def}{2025-03-10}{}
   {L3 backend support: dvisvgm}
 %</dvisvgm>
 %<*luatex>
-  {l3backend-luatex.def}{2024-05-08}{}
+  {l3backend-luatex.def}{2025-03-10}{}
   {L3 backend support: PDF output (LuaTeX)}
 %</luatex>
 %<*pdftex>
-  {l3backend-pdftex.def}{2024-05-08}{}
+  {l3backend-pdftex.def}{2025-03-10}{}
   {L3 backend support: PDF output (pdfTeX)}
 %</pdftex>
 %<*xetex>
-  {l3backend-xetex.def}{2024-05-08}{}
+  {l3backend-xetex.def}{2025-03-10}{}
   {L3 backend support: XeTeX}
 %</xetex>
 %    \end{macrocode}
@@ -280,7 +280,16 @@
 %</pdftex>
       { \exp_not:n {#1} }
   }
-\cs_generate_variant:Nn \__kernel_backend_literal_pdf:n { e }
+\cs_new_protected:Npn \__kernel_backend_literal_pdf:e #1
+  {
+%<*luatex>
+    \tex_pdfextension:D literal
+%</luatex>
+%<*pdftex>
+    \tex_pdfliteral:D
+%</pdftex>
+      {#1}
+  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -350,7 +359,16 @@
 %</pdftex>
         { \exp_not:n {#1} }
   }
-\cs_generate_variant:Nn \__kernel_backend_matrix:n { e }
+\cs_new_protected:Npn \__kernel_backend_matrix:e #1
+  {
+%<*luatex>
+    \tex_pdfextension:D setmatrix
+%</luatex>
+%<*pdftex>
+    \tex_pdfsetmatrix:D
+%</pdftex>
+        {#1}
+  }
 %    \end{macrocode}
 % \end{macro}
 %

Modified: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-box.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-box.dtx	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-box.dtx	2025-03-11 20:09:53 UTC (rev 74575)
@@ -2,7 +2,7 @@
 %
 %% File: l3backend-box.dtx
 %
-% Copyright (C) 2019-2024 The LaTeX Project
+% Copyright (C) 2019-2025 The 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
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2024-05-08}
+% \date{Released 2025-03-10}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-color.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-color.dtx	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-color.dtx	2025-03-11 20:09:53 UTC (rev 74575)
@@ -2,7 +2,7 @@
 %
 %% File: l3backend-color.dtx
 %
-% Copyright (C) 2019-2024 The LaTeX Project
+% Copyright (C) 2019-2025 The 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
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2024-05-08}
+% \date{Released 2025-03-10}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-draw.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-draw.dtx	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-draw.dtx	2025-03-11 20:09:53 UTC (rev 74575)
@@ -2,7 +2,7 @@
 %
 %% File: l3backend-draw.dtx
 %
-% Copyright (C) 2019-2024 The LaTeX Project
+% Copyright (C) 2019-2025 The 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
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2024-05-08}
+% \date{Released 2025-03-10}
 %
 % \maketitle
 %
@@ -115,7 +115,7 @@
 % \begin{macro}{\@@_backend_curveto:nnnnnn}
 %   Path creation operations mainly resolve directly to PostScript primitive
 %   steps, with only the need to convert to \texttt{bp}. Notice that
-%   \texttt{x}-type expansion is included here to ensure that any variable
+%   \texttt{e}-type expansion is included here to ensure that any variable
 %   values are forced to literals before any possible caching. There is
 %   no native rectangular path command (without also clipping, filling or
 %   stroking), so that task is done using a small amount of PostScript.
@@ -327,8 +327,8 @@
 % \end{macro}
 % \end{macro}
 %
-%
-% \begin{macro}{\@@_backend_cm:nnnn}
+% \begin{macro}{\@@_backend_transform:nnnn}
+% \begin{macro}{\@@_backend_shift:nn}
 %   In \texttt{dvips}, keeping the transformations in line with the engine
 %   is unfortunately not possible for scaling and rotations: even if we
 %   decompose the matrix into those operations, there is still no backend
@@ -335,13 +335,19 @@
 %   tracking (\emph{cf.}~\texttt{dvipdfmx}/\XeTeX{}). Thus we take the shortest
 %   path available and simply dump the matrix as given.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_cm:nnnn #1#2#3#4
+\cs_new_protected:Npn \@@_backend_transform:nnnn #1#2#3#4
   {
     \@@_backend_literal:n
       { [ #1 ~ #2 ~ #3 ~ #4 ~ 0 ~ 0 ] ~ concat }
   }
+\cs_new_protected:Npn \@@_backend_shift:nn #1#2
+  {
+    \@@_backend_literal:n
+      { [ 1 ~ 0 ~ 0 ~ 1 ~ #1 ~ #2 ] ~ concat }
+  }
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
 % \begin{macro}{\@@_backend_box_use:Nnnnn}
 %   Inside a picture |@beginspecial|/|@endspecial| are active, which is
@@ -369,9 +375,9 @@
     \@@_backend_literal:n { save }
     \@@_backend_literal:n { currentpoint }
     \@@_backend_literal:n { currentpoint~translate }
-    \@@_backend_cm:nnnn { 1 } { 0 } { 0 } { -1 }
-    \@@_backend_cm:nnnn {#2} {#3} {#4} {#5}
-    \@@_backend_cm:nnnn { 1 } { 0 } { 0 } { -1 }
+    \@@_backend_transform:nnnn { 1 } { 0 } { 0 } { -1 }
+    \@@_backend_transform:nnnn {#2} {#3} {#4} {#5}
+    \@@_backend_transform:nnnn { 1 } { 0 } { 0 } { -1 }
     \@@_backend_literal:n { neg~exch~neg~exch~translate }
     \@@_backend_literal:n { [end] }
     \hbox_overlap_right:n { \box_use:N #1 }
@@ -403,7 +409,7 @@
 %   Pass data through using a dedicated interface.
 %    \begin{macrocode}
 \cs_new_eq:NN \@@_backend_literal:n \__kernel_backend_literal_pdf:n
-\cs_generate_variant:Nn \@@_backend_literal:n { e }
+\cs_new_eq:NN \@@_backend_literal:e \__kernel_backend_literal_pdf:e
 %    \end{macrocode}
 % \end{macro}
 %
@@ -568,8 +574,9 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}{\@@_backend_cm:nnnn}
-% \begin{macro}{\@@_backend_cm_aux:nnnn}
+% \begin{macro}{\@@_backend_transform:nnnn}
+% \begin{macro}{\@@_backend_transform_aux:nnnn}
+% \begin{macro}{\@@_backend_shift:nn}
 %   Another split here between \LuaTeX{}/pdfTeX{} and \texttt{dvipdfmx}/\XeTeX{}.
 %   In the former, we have a direct method to maintain alignment: the backend
 %   can use a matrix itself. For \texttt{dvipdfmx}/\XeTeX{}, we can to decompose the
@@ -578,20 +585,30 @@
 %   \texttt{dvipdfmx}/\XeTeX{}, but as a matched pair so not suitable for the
 %   \enquote{stand alone} transformation set up here.) The specials used here
 %   are from \texttt{xdvipdfmx} originally: they are well-tested, but probably
-%   equivalent to the \texttt{pdf:} versions!
+%   equivalent to the \texttt{pdf:} versions! As working out the rotation is
+%   relatively expensive, we optimise for the case where there is only a
+%   scaling.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_cm:nnnn #1#2#3#4
+\cs_new_protected:Npn \@@_backend_transform:nnnn #1#2#3#4
   {
 %<*luatex|pdftex>
     \__kernel_backend_matrix:n { #1 ~ #2 ~ #3 ~ #4 }
 %</luatex|pdftex>
 %<*dvipdfmx|xetex>
-    \@@_backend_cm_decompose:nnnnN {#1} {#2} {#3} {#4}
-      \@@_backend_cm_aux:nnnn
+    \str_if_eq:nnTF { #2 ~ #3 } { 0 ~ 0 }
+      {
+        \__kernel_backend_literal:n { x:rotate~0 }
+        \__kernel_backend_literal:n { x:scale~#1~#4 }
+        \__kernel_backend_literal:n { x:rotate~0 }
+      }
+      {
+        \@@_backend_transform_decompose:nnnnN {#1} {#2} {#3} {#4}
+          \@@_backend_transform_aux:nnnn
+      }
 %</dvipdfmx|xetex>
   }
 %<*dvipdfmx|xetex>
-\cs_new_protected:Npn \@@_backend_cm_aux:nnnn #1#2#3#4
+\cs_new_protected:Npn \@@_backend_transform_aux:nnnn #1#2#3#4
   {
     \__kernel_backend_literal:e
       {
@@ -616,15 +633,26 @@
   }
 %</dvipdfmx|xetex>
 %    \end{macrocode}
+%   Much less complex for a shift: this is deliberately not tracked by the
+%   engine (we would otherwise do stuff in \TeX{}), so use the same approach
+%   for all PDF-based routes.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_shift:nn #1#2
+  {
+    \@@_backend_literal:n
+      { 1 ~ 0 ~ 0 ~ 1 ~ #1 ~ #2 ~ cm }
+  }
+%    \end{macrocode}
 % \end{macro}
 % \end{macro}
+% \end{macro}
 %
-% \begin{macro}{\@@_backend_cm_decompose:nnnnN}
+% \begin{macro}{\@@_backend_transform_decompose:nnnnN}
 % \begin{macro}
 %   {
-%     \@@_backend_cm_decompose_auxi:nnnnN,
-%     \@@_backend_cm_decompose_auxii:nnnnN,
-%     \@@_backend_cm_decompose_auxiii:nnnnN,
+%     \@@_backend_transform_decompose_auxi:nnnnN,
+%     \@@_backend_transform_decompose_auxii:nnnnN,
+%     \@@_backend_transform_decompose_auxiii:nnnnN,
 %   }
 %   Internally, transformations for drawing are tracked as a matrix. Not all
 %   engines provide a way of dealing with this: if we use a raw matrix, the
@@ -675,11 +703,11 @@
 %   normally expect $B$ and $C$ to be.
 %    \begin{macrocode}
 %<*dvipdfmx|xetex>
-\cs_new_protected:Npn \@@_backend_cm_decompose:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \@@_backend_transform_decompose:nnnnN #1#2#3#4#5
   {
     \use:e
       {
-        \@@_backend_cm_decompose_auxi:nnnnN
+        \@@_backend_transform_decompose_auxi:nnnnN
           { \fp_eval:n { (#1 + #4) / 2 } }
           { \fp_eval:n { (#1 - #4) / 2 } }
           { \fp_eval:n { (#3 + #2) / 2 } }
@@ -687,11 +715,11 @@
       }
         #5
   }
-\cs_new_protected:Npn \@@_backend_cm_decompose_auxi:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \@@_backend_transform_decompose_auxi:nnnnN #1#2#3#4#5
   {
     \use:e
       {
-        \@@_backend_cm_decompose_auxii:nnnnN
+        \@@_backend_transform_decompose_auxii:nnnnN
           { \fp_eval:n { 2 * sqrt ( #1 * #1 + #4 * #4 ) } }
           { \fp_eval:n { 2 * sqrt ( #2 * #2 + #3 * #3 ) } }
           { \fp_eval:n { atand ( #3 , #2 ) } }
@@ -699,11 +727,11 @@
       }
         #5
   }
-\cs_new_protected:Npn \@@_backend_cm_decompose_auxii:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \@@_backend_transform_decompose_auxii:nnnnN #1#2#3#4#5
   {
     \use:e
       {
-        \@@_backend_cm_decompose_auxiii:nnnnN
+        \@@_backend_transform_decompose_auxiii:nnnnN
           { \fp_eval:n { ( #4 - #3 ) / 2 } }
           { \fp_eval:n { ( #1 + #2 ) / 2 } }
           { \fp_eval:n { ( #1 - #2 ) / 2 } }
@@ -711,7 +739,7 @@
       }
         #5
   }
-\cs_new_protected:Npn \@@_backend_cm_decompose_auxiii:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \@@_backend_transform_decompose_auxiii:nnnnN #1#2#3#4#5
   {
     \fp_compare:nNnTF { abs( #2 ) } > { abs ( #3 ) }
       { #5 {#1} {#2} {#3} {#4} }
@@ -734,7 +762,7 @@
   {
     \__kernel_backend_scope_begin:
 %<*luatex|pdftex>
-    \@@_backend_cm:nnnn {#2} {#3} {#4} {#5}
+    \__kernel_backend_matrix:n { #2 ~ #3 ~ #4 ~ #5 }
 %</luatex|pdftex>
 %<*dvipdfmx|xetex>
     \__kernel_backend_literal:n
@@ -798,7 +826,7 @@
 %   collected up before being output in one go. For that we use a dedicated
 %   storage routine, which adds spaces as required. Since paths should
 %   be fully expanded there is no need to worry about the internal
-%   \texttt{x}-type expansion.
+%   \texttt{e}-type expansion.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_backend_moveto:nn #1#2
   {
@@ -1013,11 +1041,12 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}{\@@_backend_cm:nnnn}
+% \begin{macro}{\@@_backend_transform:nnnn}
+% \begin{macro}{\@@_backend_shift:nn}
 %   The four arguments here are floats (the affine matrix), the last
 %   two are a displacement vector.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_cm:nnnn #1#2#3#4
+\cs_new_protected:Npn \@@_backend_transform:nnnn #1#2#3#4
   {
     \__kernel_backend_scope:n
       {
@@ -1025,8 +1054,17 @@
           " matrix ( #1 , #2 , #3 , #4 , 0pt , 0pt ) "
       }
   }
+\cs_new_protected:Npn \@@_backend_shift:nn #1#2
+  {
+    \__kernel_backend_scope:n
+      {
+        transform =
+          " matrix ( 1 , 0 , 0 , 1 ,  #1pt , #2pt ) "
+      }
+  }
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
 % \begin{macro}{\@@_backend_box_use:Nnnnn}
 %   No special savings can be made here: simply displace the box inside
@@ -1036,7 +1074,7 @@
 \cs_new_protected:Npn \@@_backend_box_use:Nnnnn #1#2#3#4#5
   {
     \__kernel_backend_scope_begin:
-    \@@_backend_cm:nnnn {#2} {#3} {#4} {#5}
+    \@@_backend_transform:nnnn {#2} {#3} {#4} {#5}
     \__kernel_backend_literal_svg:n
       {
         < g~

Modified: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx	2025-03-11 20:09:53 UTC (rev 74575)
@@ -2,7 +2,7 @@
 %
 %% File: l3backend-graphics.dtx
 %
-% Copyright (C) 2019-2024 The LaTeX Project
+% Copyright (C) 2019-2025 The 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
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2024-05-08}
+% \date{Released 2025-03-10}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-header.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-header.dtx	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-header.dtx	2025-03-11 20:09:53 UTC (rev 74575)
@@ -2,7 +2,7 @@
 %
 %% File: l3backend-header.dtx
 %
-% Copyright (C) 2019-2024 The LaTeX Project
+% Copyright (C) 2019-2025 The 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
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2024-05-08}
+% \date{Released 2025-03-10}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-opacity.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-opacity.dtx	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-opacity.dtx	2025-03-11 20:09:53 UTC (rev 74575)
@@ -2,7 +2,7 @@
 %
 %% File: l3backend-opacity.dtx
 %
-% Copyright (C) 2021-2024 The LaTeX Project
+% Copyright (C) 2021-2025 The 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
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2024-05-08}
+% \date{Released 2025-03-10}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdf.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdf.dtx	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdf.dtx	2025-03-11 20:09:53 UTC (rev 74575)
@@ -2,7 +2,7 @@
 %
 %% File: l3backend-pdf.dtx
 %
-% Copyright (C) 2019-2024 The LaTeX Project
+% Copyright (C) 2019-2025 The 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
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2024-05-08}
+% \date{Released 2025-03-10}
 %
 % \maketitle
 %
@@ -66,25 +66,6 @@
 % significant contributions by Alexander Grahn, in addition to the specific
 % code referenced a various points.
 %
-% \subsection{Shared code}
-%
-% A very small number of items that belong at the backend level but which
-% are common to most backends.
-%
-%    \begin{macrocode}
-%<*!dvisvgm>
-%    \end{macrocode}
-%
-% \begin{variable}{\l_@@_internal_box}
-%    \begin{macrocode}
-\box_new:N \l_@@_internal_box
-%    \end{macrocode}
-% \end{variable}
-%
-%    \begin{macrocode}
-%</!dvisvgm>
-%    \end{macrocode}
-%
 % \subsection{\texttt{dvips} backend}
 %
 %    \begin{macrocode}
@@ -238,371 +219,8 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \subsubsection{Annotations}
+% \subsubsection{Destinations}
 %
-% In \texttt{dvips}, annotations have to be constructed manually. As such,
-% we need the object code above for some definitions.
-%
-% \begin{variable}{\l_@@_backend_content_box}
-%   The content of an annotation.
-%    \begin{macrocode}
-\box_new:N \l_@@_backend_content_box
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_@@_backend_model_box}
-%   For creating model sizing for links.
-%    \begin{macrocode}
-\box_new:N \l_@@_backend_model_box
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\g_@@_backend_annotation_int}
-%   Needed as objects which are not annotations could be created.
-%    \begin{macrocode}
-\int_new:N \g_@@_backend_annotation_int
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\@@_backend_annotation:nnnn}
-%   Annotations are objects, but we track them separately. Notably, they are
-%   not in the object data lists. Here, to get the coordinates of the
-%   annotation, we need to have the data collected at the PostScript level.
-%   That requires a bit of box trickery (effectively a \LaTeXe{} |picture|
-%   of zero size). Once the data is collected, use it to set up the annotation
-%   border.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_annotation:nnnn #1#2#3#4
-  {
-    \exp_args:Nf \@@_backend_annotation_aux:nnnn
-      { \dim_eval:n {#1} } {#2} {#3} {#4}
-  }
-\cs_new_protected:Npn \@@_backend_annotation_aux:nnnn #1#2#3#4
-  {
-    \box_move_down:nn {#3}
-      { \hbox:n { \__kernel_backend_postscript:n { pdf.save.ll } } }
-    \box_move_up:nn {#2}
-      {
-        \hbox:n
-          {
-            \__kernel_kern:n {#1}
-            \__kernel_backend_postscript:n { pdf.save.ur }
-            \__kernel_kern:n { -#1 }
-          }
-      }
-    \int_gincr:N \g_@@_backend_object_int
-    \int_gset_eq:NN \g_@@_backend_annotation_int \g_@@_backend_object_int
-    \@@_backend_pdfmark:e
-      {
-        /_objdef { pdf.obj \int_use:N \g_@@_backend_object_int }
-        pdf.rect
-        #4 ~
-        /ANN
-      }
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\@@_backend_annotation_last:}
-%   Provide the last annotation we created: could get tricky of course if
-%   other packages are loaded.
-%    \begin{macrocode}
-\cs_new:Npn \@@_backend_annotation_last:
-  { { pdf.obj \int_use:N \g_@@_backend_annotation_int } }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{variable}{\g_@@_backend_link_int}
-%   To track annotations which are links.
-%    \begin{macrocode}
-\int_new:N \g_@@_backend_link_int
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\g_@@_backend_link_dict_tl}
-%   To pass information to the end-of-link function.
-%    \begin{macrocode}
-\tl_new:N \g_@@_backend_link_dict_tl
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\g_@@_backend_link_sf_int}
-%   Needed to save/restore space factor, which is needed to deal with the face
-%   we need a box.
-%    \begin{macrocode}
-\int_new:N \g_@@_backend_link_sf_int
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\g_@@_backend_link_math_bool}
-%   Needed to save/restore math mode.
-%    \begin{macrocode}
-\bool_new:N \g_@@_backend_link_math_bool
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\g_@@_backend_link_bool}
-%   Track link formation: we cannot nest at all.
-%    \begin{macrocode}
-\bool_new:N \g_@@_backend_link_bool
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_@@_breaklink_pdfmark_tl}
-%   Swappable content for link breaking.
-%    \begin{macrocode}
-\tl_new:N \l_@@_breaklink_pdfmark_tl
-\tl_set:Nn \l_@@_breaklink_pdfmark_tl { pdfmark }
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\@@_breaklink_postscript:n}
-%   To allow dropping material unless link breaking is active.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_breaklink_postscript:n #1 { }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_breaklink_usebox:N}
-%   Swappable box unpacking or use.
-%    \begin{macrocode}
-\cs_new_eq:NN \@@_breaklink_usebox:N \box_use:N
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_backend_link_begin_goto:nnw, \@@_backend_link_begin_user:nnw}
-% \begin{macro}{\@@_backend_link:nw, \@@_backend_link_aux:nw}
-% \begin{macro}{\@@_backend_link_end:, \@@_backend_link_end_aux:}
-% \begin{macro}{\@@_backend_link_minima:}
-% \begin{macro}{\@@_backend_link_outerbox:n}
-% \begin{macro}{\@@_backend_link_sf_save:, \@@_backend_link_sf_restore:}
-%   Links are created like annotations but with dedicated code to allow for
-%   adjusting the size of the rectangle. In contrast to \pkg{hyperref}, we
-%   grab the link content as a box which can then unbox: this allows the same
-%   interface as for \pdfTeX{}.
-%
-%   Notice that the link setup here uses |/Action| not |/A|. That is because
-%   Distiller \emph{requires} this trigger word, rather than a \enquote{raw}
-%   PDF dictionary key (Ghostscript can handle either form).
-%
-%   Taking the idea of |evenboxes| from \pkg{hypdvips}, we implement a minimum
-%   box height and depth for link placement. This means that \enquote{underlining}
-%   with a hyperlink will generally give an even appearance. However, to ensure
-%   that the full content is always above the link border, we do not allow
-%   this to be negative (contrast \pkg{hypdvips} approach). The result should
-%   be similar to \pdfTeX{} in the vast majority of foreseeable cases.
-%
-%   The object number for a link is saved separately from the rest of the
-%   dictionary as this allows us to insert it just once, at either an
-%   unbroken link or only in the first line of a broken one. That makes the
-%   code clearer but also avoids a low-level PostScript error with the code
-%   as taken from \pkg{hypdvips}.
-%
-%   Getting the outer dimensions of the text area may be better using a two-pass
-%   approach and |\tex_savepos:D|. That plus generic mode are still to re-examine.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_link_begin_goto:nnw #1#2
-  {
-    \@@_backend_link_begin:nw
-      { #1 /Subtype /Link /Action << /S /GoTo /D ( #2 ) >> }
-  }
-\cs_new_protected:Npn \@@_backend_link_begin_user:nnw #1#2
-  { \@@_backend_link_begin:nw {#1#2} }
-\cs_new_protected:Npn \@@_backend_link_begin:nw #1
-  {
-    \bool_if:NF \g_@@_backend_link_bool
-      { \@@_backend_link_begin_aux:nw {#1} }
-  }
-%    \end{macrocode}
-%   The definition of |pdf.link.dict| here is needed as there is code in the
-%   PostScript headers for breaking links, and that can only work with this
-%   available.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_link_begin_aux:nw #1
-  {
-    \bool_gset_true:N \g_@@_backend_link_bool
-    \__kernel_backend_postscript:n
-      { /pdf.link.dict ( #1 ) def }
-    \tl_gset:Nn \g_@@_backend_link_dict_tl {#1}
-    \@@_backend_link_sf_save:
-    \mode_if_math:TF
-      { \bool_gset_true:N \g_@@_backend_link_math_bool }
-      { \bool_gset_false:N \g_@@_backend_link_math_bool }
-    \hbox_set:Nw \l_@@_backend_content_box
-      \@@_backend_link_sf_restore:
-      \bool_if:NT \g_@@_backend_link_math_bool
-        { \c_math_toggle_token }
-  }
-\cs_new_protected:Npn \@@_backend_link_end:
-  {
-    \bool_if:NT \g_@@_backend_link_bool
-      { \@@_backend_link_end_aux: }
-  }
-\cs_new_protected:Npn \@@_backend_link_end_aux:
-  {
-      \bool_if:NT \g_@@_backend_link_math_bool
-        { \c_math_toggle_token }
-      \@@_backend_link_sf_save:
-    \hbox_set_end:
-    \@@_backend_link_minima:
-    \hbox_set:Nn \l_@@_backend_model_box { Gg }
-    \exp_args:Ne \@@_backend_link_outerbox:n
-      {
-        \int_if_odd:nTF { \value { page } }
-          { \oddsidemargin }
-          { \evensidemargin }
-      }
-    \box_move_down:nn { \box_dp:N \l_@@_backend_content_box }
-      { \hbox:n { \__kernel_backend_postscript:n { pdf.save.linkll } } }
-    \@@_breaklink_postscript:n { pdf.bordertracking.begin }
-    \@@_breaklink_usebox:N \l_@@_backend_content_box
-    \@@_breaklink_postscript:n { pdf.bordertracking.end }
-    \box_move_up:nn { \box_ht:N \l_@@_backend_content_box }
-      {
-        \hbox:n
-          { \__kernel_backend_postscript:n { pdf.save.linkur } }
-      }
-    \int_gincr:N \g_@@_backend_object_int
-    \int_gset_eq:NN \g_@@_backend_link_int \g_@@_backend_object_int
-    \__kernel_backend_postscript:e
-      {
-        mark
-        /_objdef { pdf.obj \int_use:N \g_@@_backend_link_int }
-        \g_@@_backend_link_dict_tl \c_space_tl
-        pdf.rect
-        /ANN ~ \l_@@_breaklink_pdfmark_tl
-      }
-    \@@_backend_link_sf_restore:
-    \bool_gset_false:N \g_@@_backend_link_bool
-  }
-\cs_new_protected:Npn \@@_backend_link_minima:
-  {
-    \hbox_set:Nn \l_@@_backend_model_box { Gg }
-    \__kernel_backend_postscript:e
-      {
-        /pdf.linkdp.pad ~
-          \dim_to_decimal:n
-            {
-              \dim_max:nn
-                {
-                    \box_dp:N \l_@@_backend_model_box
-                  - \box_dp:N \l_@@_backend_content_box
-                }
-                { 0pt }
-            } ~
-              pdf.pt.dvi ~ def
-        /pdf.linkht.pad ~
-          \dim_to_decimal:n
-            {
-              \dim_max:nn
-                {
-                    \box_ht:N \l_@@_backend_model_box
-                  - \box_ht:N \l_@@_backend_content_box
-                }
-                { 0pt }
-            } ~
-              pdf.pt.dvi ~ def
-      }
-  }
-\cs_new_protected:Npn \@@_backend_link_outerbox:n #1
-  {
-    \__kernel_backend_postscript:e
-      {
-        /pdf.outerbox
-          [
-            \dim_to_decimal:n {#1} ~
-            \dim_to_decimal:n { -\box_dp:N \l_@@_backend_model_box } ~
-            \dim_to_decimal:n { #1 + \textwidth } ~
-            \dim_to_decimal:n { \box_ht:N \l_@@_backend_model_box }
-          ]
-          [ exch { pdf.pt.dvi } forall ] def
-        /pdf.baselineskip ~
-          \dim_to_decimal:n { \tex_baselineskip:D } ~ dup ~ 0 ~ gt
-            { pdf.pt.dvi ~ def }
-            { pop ~ pop }
-          ifelse
-      }
-  }
-\cs_new_protected:Npn \@@_backend_link_sf_save:
-  {
-    \int_gset:Nn \g_@@_backend_link_sf_int
-      {
-        \mode_if_horizontal:TF
-          { \tex_spacefactor:D }
-          { 0 }
-      }
-  }
-\cs_new_protected:Npn \@@_backend_link_sf_restore:
-  {
-    \mode_if_horizontal:T
-      {
-        \int_compare:nNnT \g_@@_backend_link_sf_int > { 0 }
-          { \int_set_eq:NN \tex_spacefactor:D \g_@@_backend_link_sf_int }
-      }
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-%   Hooks to allow link breaking: something will be needed in format mode
-%   at some stage. At present this code is disabled as there is an open
-%   question about the name of the hook: to be resolved at the \LaTeXe{}
-%   end.
-%    \begin{macrocode}
-\use_none:n
-  {
-    \cs_if_exist:NT \@makecol at hook
-      {
-        \tl_put_right:Nn \@makecol at hook
-          {
-            \box_if_empty:NF \l_shipout_box
-              {
-                \vbox_set:Nn \l_shipout_box
-                  {
-                    \__kernel_backend_postscript:n
-                      {
-                        pdf.globaldict /pdf.brokenlink.rect ~ known
-                          { pdf.bordertracking.continue }
-                        if
-                      }
-                    \vbox_unpack_drop:N \l_shipout_box
-                    \__kernel_backend_postscript:n
-                      { pdf.bordertracking.endpage }
-                  }
-              }
-          }
-        \tl_set:Nn \l_@@_breaklink_pdfmark_tl { pdf.pdfmark }
-        \cs_set_eq:NN \@@_breaklink_postscript:n \__kernel_backend_postscript:n
-        \cs_set_eq:NN \@@_breaklink_usebox:N \hbox_unpack:N
-      }
-  }
-%    \end{macrocode}
-%
-% \begin{macro}{\@@_backend_link_last:}
-%   The same as annotations, but with a custom integer.
-%    \begin{macrocode}
-\cs_new:Npn \@@_backend_link_last:
-  { { pdf.obj \int_use:N \g_@@_backend_link_int } }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_backend_link_margin:n}
-%   Convert to big points and pass to PostScript.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_link_margin:n #1
-  {
-    \__kernel_backend_postscript:e
-      {
-        /pdf.linkmargin { \dim_to_decimal:n {#1} ~ pdf.pt.dvi } def
-      }
-  }
-%    \end{macrocode}
-% \end{macro}
-%
 % \begin{macro}{\@@_backend_destination:nn}
 % \begin{macro}{\@@_backend_destination:nnnn, \@@_backend_destination_aux:nnnn}
 %   Here, we need to turn the zoom into a scale. We also need to know where
@@ -753,115 +371,8 @@
 %<*luatex|pdftex>
 %    \end{macrocode}
 %
-% \subsubsection{Annotations}
+% \subsubsection{Destinations}
 %
-% \begin{macro}{\@@_backend_annotation:nnnn}
-%   Simply pass the raw data through, just dealing with evaluation of dimensions.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_annotation:nnnn #1#2#3#4
-  {
-%<*luatex>
-    \tex_pdfextension:D annot ~
-%</luatex>
-%<*pdftex>
-    \tex_pdfannot:D
-%</pdftex>
-      width  ~ \dim_eval:n {#1} ~
-      height ~ \dim_eval:n {#2} ~
-      depth  ~ \dim_eval:n {#3} ~
-      {#4}
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\@@_backend_annotation_last:}
-%   A tiny amount of extra data gets added here; we use \texttt{x}-type
-%   expansion to get the space in the right place and form. The \enquote{extra}
-%   space in the \LuaTeX{} version is \emph{required} as it is consumed in
-%   finding the end of the keyword.
-%    \begin{macrocode}
-\cs_new:Npe \@@_backend_annotation_last:
-  {
-    \exp_not:N \int_value:w
-%<*luatex>
-      \exp_not:N \tex_pdffeedback:D lastannot ~
-%</luatex>
-%<*pdftex>
-      \exp_not:N \tex_pdflastannot:D
-%</pdftex>
-      \c_space_tl 0 ~ R
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}
-%   {\@@_backend_link_begin_goto:nnw, \@@_backend_link_begin_user:nnw}
-% \begin{macro}{\@@_backend_link_begin:nnnw}
-% \begin{macro}{\@@_backend_link_end:}
-%   Links are all created using the same internals.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_link_begin_goto:nnw #1#2
-  { \@@_backend_link_begin:nnnw {#1} { goto~name } {#2} }
-\cs_new_protected:Npn \@@_backend_link_begin_user:nnw #1#2
-  { \@@_backend_link_begin:nnnw {#1} { user } {#2} }
-\cs_new_protected:Npn \@@_backend_link_begin:nnnw #1#2#3
-  {
-%<*luatex>
-    \tex_pdfextension:D startlink ~
-%</luatex>
-%<*pdftex>
-    \tex_pdfstartlink:D
-%</pdftex>
-      attr {#1}
-      #2 {#3}
-  }
-\cs_new_protected:Npn \@@_backend_link_end:
-  {
-%<*luatex>
-    \tex_pdfextension:D endlink \scan_stop:
-%</luatex>
-%<*pdftex>
-    \tex_pdfendlink:D
-%</pdftex>
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\@@_backend_link_last:}
-%   Formatted for direct use.
-%    \begin{macrocode}
-\cs_new:Npe \@@_backend_link_last:
-  {
-    \exp_not:N \int_value:w
-%<*luatex>
-      \exp_not:N \tex_pdffeedback:D lastlink ~
-%</luatex>
-%<*pdftex>
-      \exp_not:N \tex_pdflastlink:D
-%</pdftex>
-      \c_space_tl 0 ~ R
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_backend_link_margin:n}
-%   A simple task: pass the data to the primitive.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_link_margin:n #1
-  {
-%<*luatex>
-    \tex_pdfvariable:D linkmargin
-%</luatex>
-%<*pdftex>
-    \tex_pdflinkmargin:D
-%</pdftex>
-      \dim_eval:n {#1} \scan_stop:
-  }
-%    \end{macrocode}
-% \end{macro}
-%
 % \begin{macro}{\@@_backend_destination:nn}
 % \begin{macro}{\@@_backend_destination:nnnn}
 %   A simple task: pass the data to the primitive. The |\scan_stop:| deals
@@ -1314,97 +825,8 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \subsubsection{Annotations}
+% \subsubsection{Destinations}
 %
-% \begin{variable}{\g_@@_backend_annotation_int}
-%   Needed as objects which are not annotations could be created.
-%    \begin{macrocode}
-\int_new:N \g_@@_backend_annotation_int
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\@@_backend_annotation:nnnn}
-%   Simply pass the raw data through, just dealing with evaluation of dimensions.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_annotation:nnnn #1#2#3#4
-  {
-    \int_gincr:N \g_@@_backend_object_int
-    \int_gset_eq:NN \g_@@_backend_annotation_int \g_@@_backend_object_int
-    \@@_backend:e
-      {
-        ann ~ @pdf.obj \int_use:N \g_@@_backend_object_int \c_space_tl
-        width  ~ \dim_eval:n {#1} ~
-        height ~ \dim_eval:n {#2} ~
-        depth  ~ \dim_eval:n {#3} ~
-        << /Type /Annot #4 >>
-      }
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_backend_annotation_last:}
-%    \begin{macrocode}
-\cs_new:Npn \@@_backend_annotation_last:
-  { @pdf.obj \int_use:N \g_@@_backend_annotation_int }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{variable}{\g_@@_backend_link_int}
-%   To track annotations which are links.
-%    \begin{macrocode}
-\int_new:N \g_@@_backend_link_int
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}
-%   {\@@_backend_link_begin_goto:nnw, \@@_backend_link_begin_user:nnw}
-% \begin{macro}{\@@_backend_link_begin:n}
-% \begin{macro}{\@@_backend_link_end:}
-%   All created using the same internals.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_link_begin_goto:nnw #1#2
-  { \@@_backend_link_begin:n { #1 /Subtype /Link /A << /S /GoTo /D ( #2 ) >> } }
-\cs_new_protected:Npn \@@_backend_link_begin_user:nnw #1#2
-  { \@@_backend_link_begin:n {#1#2} }
-\cs_new_protected:Npe \@@_backend_link_begin:n #1
-  {
-    \exp_not:N \int_gincr:N \exp_not:N  \g_@@_backend_link_int
-    \@@_backend:e
-      {
-        bann ~
-        @pdf.lnk
-        \exp_not:N \int_use:N \exp_not:N  \g_@@_backend_link_int
-        \c_space_tl
-        <<
-          /Type /Annot
-          #1
-        >>
-      }
-  }
-\cs_new_protected:Npn \@@_backend_link_end:
-  { \@@_backend:n { eann } }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\@@_backend_link_last:}
-%   Available using the backend mechanism with a suitably-recent
-%   version.
-%    \begin{macrocode}
-\cs_new:Npn \@@_backend_link_last:
-  { @pdf.lnk \int_use:N \g_@@_backend_link_int }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_backend_link_margin:n}
-%   Pass to \texttt{dvipdfmx}.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_link_margin:n #1
-  { \__kernel_backend_literal:e { dvipdfmx:config~g~ \dim_eval:n {#1} } }
-%    \end{macrocode}
-% \end{macro}
-%
 % \begin{macro}{\@@_backend_destination:nn}
 % \begin{macro}{\@@_backend_destination:nnnn,\@@_backend_destination_aux:nnnn}
 %   Here, we need to turn the zoom into a scale. The method for \texttt{FitR}
@@ -1544,47 +966,8 @@
 %<*dvisvgm>
 %    \end{macrocode}
 %
-% \subsubsection{Annotations}
+% \subsubsection{Destinations}
 %
-% \begin{macro}{\@@_backend_annotation:nnnn}
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_annotation:nnnn #1#2#3#4 { }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\@@_backend_annotation_last:}
-%    \begin{macrocode}
-\cs_new:Npn \@@_backend_annotation_last: { }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}
-%   {\@@_backend_link_begin_goto:nnw, \@@_backend_link_begin_user:nnw}
-% \begin{macro}{\@@_backend_link_begin:nnnw}
-% \begin{macro}{\@@_backend_link_end:}
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_link_begin_goto:nnw #1#2 { }
-\cs_new_protected:Npn \@@_backend_link_begin_user:nnw #1#2 { }
-\cs_new_protected:Npn \@@_backend_link_begin:nnnw #1#2#3 { }
-\cs_new_protected:Npn \@@_backend_link_end: { }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\@@_backend_link_last:}
-%    \begin{macrocode}
-\cs_new:Npe \@@_backend_link_last: { }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_backend_link_margin:n}
-%   A simple task: pass the data to the primitive.
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_link_margin:n #1 { }
-%    \end{macrocode}
-% \end{macro}
-%
 % \begin{macro}{\@@_backend_destination:nn}
 % \begin{macro}{\@@_backend_destination:nnnn}
 %    \begin{macrocode}

Added: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdfannot.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdfannot.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdfannot.dtx	2025-03-11 20:09:53 UTC (rev 74575)
@@ -0,0 +1,785 @@
+% \iffalse meta-comment
+%
+%% File: l3backend-pdfannot.dtx
+%
+% Copyright (C) 2025 The 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
+%
+% This file is part of the "l3backend 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/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full,kernel]{l3doc}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+%   The \pkg{l3backend-pdfannot} module\\ Backend PDF annotation features^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2025-03-10}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3backend-pdfannot} implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%<@@=pdfannot>
+%    \end{macrocode}
+%
+% \subsection{\texttt{dvips} backend}
+%
+%    \begin{macrocode}
+%<*dvips>
+%    \end{macrocode}
+%
+% In \texttt{dvips}, annotations have to be constructed manually. As such,
+% we need the object code above for some definitions.
+%
+% \begin{variable}{\l_@@_backend_content_box}
+%   The content of an annotation.
+%    \begin{macrocode}
+\box_new:N \l_@@_backend_content_box
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_backend_model_box}
+%   For creating model sizing for links.
+%    \begin{macrocode}
+\box_new:N \l_@@_backend_model_box
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_backend_int}
+%   Needed to track annotations.
+%    \begin{macrocode}
+\int_new:N \g_@@_backend_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_backend_generic:nnnn, \@@_backend_generic_aux:nnnn}
+%   Annotations are objects but they are not in the object data lists. Here, to
+%   get the coordinates of the annotation, we need to have the data collected
+%   at the PostScript level. That requires a bit of box trickery (effectively a
+%   \LaTeXe{} |picture| of zero size). Once the data is collected, use it to
+%   set up the annotation border.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_generic:nnnn #1#2#3#4
+  {
+    \exp_args:Nf \@@_backend_generic_aux:nnnn
+      { \dim_eval:n {#1} } {#2} {#3} {#4}
+  }
+\cs_new_protected:Npn \@@_backend_generic_aux:nnnn #1#2#3#4
+  {
+    \box_move_down:nn {#3}
+      { \hbox:n { \__kernel_backend_postscript:n { pdfannot.save.ll } } }
+    \box_move_up:nn {#2}
+      {
+        \hbox:n
+          {
+            \__kernel_kern:n {#1}
+            \__kernel_backend_postscript:n { pdfannot.save.ur }
+            \__kernel_kern:n { -#1 }
+          }
+      }
+    \int_gincr:N \g_@@_backend_int
+    \__kernel_backend_postscript:e
+      {
+        mark
+        /_objdef { pdfannot \int_use:N \g_@@_backend_int }
+        pdfannot.rect
+        #4 ~
+        /ANN ~
+        pdfmark
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_backend_last:}
+%   Provide the last annotation we created: could get tricky of course if
+%   other packages are loaded.
+%    \begin{macrocode}
+\cs_new:Npn \@@_backend_last:
+  { { pdfannot \int_use:N \g_@@_backend_int } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\g_@@_backend_link_int}
+%   To track annotations which are links.
+%    \begin{macrocode}
+\int_new:N \g_@@_backend_link_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_backend_link_dict_tl}
+%   To pass information to the end-of-link function.
+%    \begin{macrocode}
+\tl_new:N \g_@@_backend_link_dict_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_backend_link_sf_int}
+%   Needed to save/restore space factor, which is needed to deal with the face
+%   we need a box.
+%    \begin{macrocode}
+\int_new:N \g_@@_backend_link_sf_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_backend_link_math_bool}
+%   Needed to save/restore math mode.
+%    \begin{macrocode}
+\bool_new:N \g_@@_backend_link_math_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_backend_link_bool}
+%   Track link formation: we cannot nest at all.
+%    \begin{macrocode}
+\bool_new:N \g_@@_backend_link_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_backend_breaklink_pdfmark_tl}
+%   Swappable content for link breaking.
+%    \begin{macrocode}
+\tl_new:N \l_@@_backend_breaklink_pdfmark_tl
+\tl_set:Nn \l_@@_backend_breaklink_pdfmark_tl { pdfmark }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_backend_breaklink_postscript:n}
+%   To allow dropping material unless link breaking is active.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_breaklink_postscript:n #1 { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_breaklink_usebox:N}
+%   Swappable box unpacking or use.
+%    \begin{macrocode}
+\cs_new_eq:NN \@@_backend_breaklink_usebox:N \box_use:N
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {\@@_backend_link_begin_goto:nnw, \@@_backend_link_begin_user:nnw}
+% \begin{macro}{\@@_backend_link:nw, \@@_backend_link_aux:nw}
+% \begin{macro}{\@@_backend_link_end:, \@@_backend_link_end_aux:}
+% \begin{macro}{\@@_backend_link_minima:}
+% \begin{macro}{\@@_backend_link_outerbox:n}
+% \begin{macro}{\@@_backend_link_sf_save:, \@@_backend_link_sf_restore:}
+%   Links are created like annotations but with dedicated code to allow for
+%   adjusting the size of the rectangle. In contrast to \pkg{hyperref}, we
+%   grab the link content as a box which can then unbox: this allows the same
+%   interface as for \pdfTeX{}.
+%
+%   Notice that the link setup here uses |/Action| not |/A|. That is because
+%   Distiller \emph{requires} this trigger word, rather than a \enquote{raw}
+%   PDF dictionary key (Ghostscript can handle either form).
+%
+%   Taking the idea of |evenboxes| from \pkg{hypdvips}, we implement a minimum
+%   box height and depth for link placement. This means that \enquote{underlining}
+%   with a hyperlink will generally give an even appearance. However, to ensure
+%   that the full content is always above the link border, we do not allow
+%   this to be negative (contrast \pkg{hypdvips} approach). The result should
+%   be similar to \pdfTeX{} in the vast majority of foreseeable cases.
+%
+%   The object number for a link is saved separately from the rest of the
+%   dictionary as this allows us to insert it just once, at either an
+%   unbroken link or only in the first line of a broken one. That makes the
+%   code clearer but also avoids a low-level PostScript error with the code
+%   as taken from \pkg{hypdvips}.
+%
+%   Getting the outer dimensions of the text area may be better using a two-pass
+%   approach and |\tex_savepos:D|. That plus generic mode are still to re-examine.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_begin_goto:nnw #1#2
+  {
+    \@@_backend_link_begin:nw
+      { #1 /Subtype /Link /Action << /S /GoTo /D ( #2 ) >> }
+  }
+\cs_new_protected:Npn \@@_backend_link_begin_user:nnw #1#2
+  { \@@_backend_link_begin:nw {#1#2} }
+\cs_new_protected:Npn \@@_backend_link_begin:nw #1
+  {
+    \bool_if:NF \g_@@_backend_link_bool
+      { \@@_backend_link_begin_aux:nw {#1} }
+  }
+%    \end{macrocode}
+%   The definition of |pdfannot.link.dict| here is needed as there is code in the
+%   PostScript headers for breaking links, and that can only work with this
+%   available.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_begin_aux:nw #1
+  {
+    \bool_gset_true:N \g_@@_backend_link_bool
+    \__kernel_backend_postscript:n
+      { /pdfannot.link.dict ( #1 ) def }
+    \tl_gset:Nn \g_@@_backend_link_dict_tl {#1}
+    \@@_backend_link_sf_save:
+    \mode_if_math:TF
+      { \bool_gset_true:N \g_@@_backend_link_math_bool }
+      { \bool_gset_false:N \g_@@_backend_link_math_bool }
+    \hbox_set:Nw \l_@@_backend_content_box
+      \@@_backend_link_sf_restore:
+      \bool_if:NT \g_@@_backend_link_math_bool
+        { \c_math_toggle_token }
+  }
+\cs_new_protected:Npn \@@_backend_link_end:
+  {
+    \bool_if:NT \g_@@_backend_link_bool
+      { \@@_backend_link_end_aux: }
+  }
+\cs_new_protected:Npn \@@_backend_link_end_aux:
+  {
+      \bool_if:NT \g_@@_backend_link_math_bool
+        { \c_math_toggle_token }
+      \@@_backend_link_sf_save:
+    \hbox_set_end:
+    \@@_backend_link_minima:
+    \hbox_set:Nn \l_@@_backend_model_box { Gg }
+    \exp_args:Ne \@@_backend_link_outerbox:n
+      {
+        \int_if_odd:nTF { \value { page } }
+          { \oddsidemargin }
+          { \evensidemargin }
+      }
+    \box_move_down:nn { \box_dp:N \l_@@_backend_content_box }
+      { \hbox:n { \__kernel_backend_postscript:n { pdfannot.save.linkll } } }
+    \@@_backend_breaklink_postscript:n { pdfannot.bordertracking.begin }
+    \@@_backend_breaklink_usebox:N \l_@@_backend_content_box
+    \@@_backend_breaklink_postscript:n { pdfannot.bordertracking.end }
+    \box_move_up:nn { \box_ht:N \l_@@_backend_content_box }
+      {
+        \hbox:n
+          { \__kernel_backend_postscript:n { pdfannot.save.linkur } }
+      }
+    \int_gincr:N \g_@@_backend_int
+    \int_gset_eq:NN \g_@@_backend_link_int \g_@@_backend_int
+    \__kernel_backend_postscript:e
+      {
+        mark
+        /_objdef { pdfannot \int_use:N \g_@@_backend_link_int }
+        \g_@@_backend_link_dict_tl \c_space_tl
+        pdfannot.rect
+        /ANN ~ \l_@@_backend_breaklink_pdfmark_tl
+      }
+    \@@_backend_link_sf_restore:
+    \bool_gset_false:N \g_@@_backend_link_bool
+  }
+\cs_new_protected:Npn \@@_backend_link_minima:
+  {
+    \hbox_set:Nn \l_@@_backend_model_box { Gg }
+    \__kernel_backend_postscript:e
+      {
+        /pdfannot.linkdp.pad ~
+          \dim_to_decimal:n
+            {
+              \dim_max:nn
+                {
+                    \box_dp:N \l_@@_backend_model_box
+                  - \box_dp:N \l_@@_backend_content_box
+                }
+                { 0pt }
+            } ~
+              pdfannot.pt.dvi ~ def
+        /pdfannot.linkht.pad ~
+          \dim_to_decimal:n
+            {
+              \dim_max:nn
+                {
+                    \box_ht:N \l_@@_backend_model_box
+                  - \box_ht:N \l_@@_backend_content_box
+                }
+                { 0pt }
+            } ~
+              pdfannot.pt.dvi ~ def
+      }
+  }
+\cs_new_protected:Npn \@@_backend_link_outerbox:n #1
+  {
+    \__kernel_backend_postscript:e
+      {
+        /pdfannot.outerbox
+          [
+            \dim_to_decimal:n {#1} ~
+            \dim_to_decimal:n { -\box_dp:N \l_@@_backend_model_box } ~
+            \dim_to_decimal:n { #1 + \textwidth } ~
+            \dim_to_decimal:n { \box_ht:N \l_@@_backend_model_box }
+          ]
+          [ exch { pdfannot.pt.dvi } forall ] def
+        /pdfannot.baselineskip ~
+          \dim_to_decimal:n { \tex_baselineskip:D } ~ dup ~ 0 ~ gt
+            { pdfannot.pt.dvi ~ def }
+            { pop ~ pop }
+          ifelse
+      }
+  }
+\cs_new_protected:Npn \@@_backend_link_sf_save:
+  {
+    \int_gset:Nn \g_@@_backend_link_sf_int
+      {
+        \mode_if_horizontal:TF
+          { \tex_spacefactor:D }
+          { 0 }
+      }
+  }
+\cs_new_protected:Npn \@@_backend_link_sf_restore:
+  {
+    \mode_if_horizontal:T
+      {
+        \int_compare:nNnT \g_@@_backend_link_sf_int > { 0 }
+          { \int_set:Nn \tex_spacefactor:D \g_@@_backend_link_sf_int }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% Hooks to allow link breaking: something will be needed in format mode
+% at some stage. At present this code is disabled, pending a decision to
+% activate.
+%    \begin{macrocode}
+\use_none:nnn
+\cs_if_exist:NT \hook_gput_code:nnn
+  {
+    \hook_gput_code:nnn { build/column/after } { backend }
+      {
+        \box_if_empty:NF \l_shipout_box
+          {
+            \vbox_set:Nn \l_shipout_box
+              {
+                \__kernel_backend_postscript:n
+                  {
+                    pdfannot.globaldict /pdfannot.brokenlink.rect ~ known
+                      { pdfannot.bordertracking.continue }
+                    if
+                  }
+                \vbox_unpack_drop:N \l_shipout_box
+                \__kernel_backend_postscript:n
+                  { pdfannot.bordertracking.endpage }
+              }
+          }
+      }
+    \tl_set:Nn \l_@@_backend_breaklink_pdfmark_tl { pdfannot.pdfmark }
+    \cs_set_eq:NN \@@_backend_breaklink_postscript:n
+      \__kernel_backend_postscript:n
+    \cs_set_eq:NN \@@_backend_breaklink_usebox:N \hbox_unpack:N
+  }
+%    \end{macrocode}
+%
+% \begin{macro}{\@@_backend_link_last:}
+%   The same as annotations, but with a custom integer.
+%    \begin{macrocode}
+\cs_new:Npn \@@_backend_link_last:
+  { { pdfannot.annot \int_use:N \g_@@_backend_link_int } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_margin:n}
+%   Convert to big points and pass to PostScript.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_margin:n #1
+  {
+    \__kernel_backend_postscript:e
+      {
+        /pdfannot.linkmargin { \dim_to_decimal:n {#1} ~ pdfannot.pt.dvi } def
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_on:, \@@_backend_link_off:}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_on:  { }
+\cs_new_protected:Npn \@@_backend_link_off: { }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</dvips>
+%    \end{macrocode}
+%
+% \subsection{\LuaTeX{} and \pdfTeX{} backend}
+%
+%    \begin{macrocode}
+%<*luatex|pdftex>
+%    \end{macrocode}
+%
+% \begin{macro}{\@@_backend_generic:nnnn}
+%   Simply pass the raw data through, just dealing with evaluation of dimensions.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_generic:nnnn #1#2#3#4
+  {
+%<*luatex>
+    \tex_pdfextension:D annot ~
+%</luatex>
+%<*pdftex>
+    \tex_pdfannot:D
+%</pdftex>
+      width  ~ \dim_eval:n {#1} ~
+      height ~ \dim_eval:n {#2} ~
+      depth  ~ \dim_eval:n {#3} ~
+      {#4}
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_backend_last:}
+%   A tiny amount of extra data gets added here; we use \texttt{e}-type
+%   expansion to get the space in the right place and form. The \enquote{extra}
+%   space in the \LuaTeX{} version is \emph{required} as it is consumed in
+%   finding the end of the keyword.
+%    \begin{macrocode}
+\cs_new:Npe \@@_backend_last:
+  {
+    \exp_not:N \int_value:w
+%<*luatex>
+      \exp_not:N \tex_pdffeedback:D lastannot ~
+%</luatex>
+%<*pdftex>
+      \exp_not:N \tex_pdflastannot:D
+%</pdftex>
+      \c_space_tl 0 ~ R
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {\@@_backend_link_begin_goto:nnw, \@@_backend_link_begin_user:nnw}
+% \begin{macro}{\@@_backend_link_begin:nnnw}
+% \begin{macro}{\@@_backend_link_end:}
+%   Links are all created using the same internals.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_begin_goto:nnw #1#2
+  { \@@_backend_link_begin:nnnw {#1} { goto~name } {#2} }
+\cs_new_protected:Npn \@@_backend_link_begin_user:nnw #1#2
+  { \@@_backend_link_begin:nnnw {#1} { user } {#2} }
+\cs_new_protected:Npn \@@_backend_link_begin:nnnw #1#2#3
+  {
+%<*luatex>
+    \tex_pdfextension:D startlink ~
+%</luatex>
+%<*pdftex>
+    \tex_pdfstartlink:D
+%</pdftex>
+      attr {#1}
+      #2 {#3}
+  }
+\cs_new_protected:Npn \@@_backend_link_end:
+  {
+%<*luatex>
+    \tex_pdfextension:D endlink \scan_stop:
+%</luatex>
+%<*pdftex>
+    \tex_pdfendlink:D
+%</pdftex>
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_last:}
+%   Formatted for direct use.
+%    \begin{macrocode}
+\cs_new:Npe \@@_backend_link_last:
+  {
+    \exp_not:N \int_value:w
+%<*luatex>
+      \exp_not:N \tex_pdffeedback:D lastlink ~
+%</luatex>
+%<*pdftex>
+      \exp_not:N \tex_pdflastlink:D
+%</pdftex>
+      \c_space_tl 0 ~ R
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_margin:n}
+%   A simple task: pass the data to the primitive.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_margin:n #1
+  {
+%<*luatex>
+    \tex_pdfvariable:D linkmargin
+%</luatex>
+%<*pdftex>
+    \tex_pdflinkmargin:D
+%</pdftex>
+      \dim_eval:n {#1} \scan_stop:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_on:, \@@_backend_link_off:}
+%   Separate definitions for the two engines.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_on:
+%<*luatex>
+  { \tex_pdfextension:D linkstate 0 ~ }
+%</luatex>
+%<*pdftex>
+   { \tex_pdfrunninglinkon:D }
+%</pdftex>
+\cs_new_protected:Npn \@@_backend_link_off:
+%<*luatex>
+  { \tex_pdfextension:D linkstate 1 ~ }
+%</luatex>
+%<*pdftex>
+  { \tex_pdfrunninglinkoff:D }
+%</pdftex>
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</luatex|pdftex>
+%    \end{macrocode}
+%
+% \subsection{\texttt{dvipdfmx} backend}
+%
+%    \begin{macrocode}
+%<*dvipdfmx|xetex>
+%    \end{macrocode}
+%
+% \begin{macro}{\@@_backend:n, \@@_backend:e}
+%   A generic function for the backend PDF specials
+%    \begin{macrocode}
+\cs_new_protected:Npe \@@_backend:n #1
+  { \__kernel_backend_literal:n { pdf: #1 } }
+\cs_generate_variant:Nn \@@_backend:n { e }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\g_@@_backend_int}
+%   Annotations are objects: but made with a separate tracker integer.
+%    \begin{macrocode}
+\int_new:N \g_@@_backend_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_backend_generic:nnnn}
+%   Simply pass the raw data through, just dealing with evaluation of dimensions.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_generic:nnnn #1#2#3#4
+  {
+    \int_gincr:N \g_@@_backend_int
+    \@@_backend:e
+      {
+        ann ~ @pdfannot \int_use:N \g_@@_backend_int \c_space_tl
+        width  ~ \dim_eval:n {#1} ~
+        height ~ \dim_eval:n {#2} ~
+        depth  ~ \dim_eval:n {#3} ~
+        << /Type /Annot #4 >>
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_last:}
+%    \begin{macrocode}
+\cs_new:Npn \@@_backend_last:
+  { @pdfannot \int_use:N \g_@@_backend_int }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\g_@@_backend_link_int}
+%   To track annotations which are links.
+%    \begin{macrocode}
+\int_new:N \g_@@_backend_link_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+%   {\@@_backend_link_begin_goto:nnw, \@@_backend_link_begin_user:nnw}
+% \begin{macro}{\@@_backend_link_begin:n}
+% \begin{macro}{\@@_backend_link_end:}
+%   All created using the same internals.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_begin_goto:nnw #1#2
+  {
+    \@@_backend_link_begin:n
+      { #1 /Subtype /Link /A << /S /GoTo /D ( #2 ) >> }
+  }
+\cs_new_protected:Npn \@@_backend_link_begin_user:nnw #1#2
+  { \@@_backend_link_begin:n {#1#2} }
+\cs_new_protected:Npe \@@_backend_link_begin:n #1
+  {
+    \int_gincr:N \exp_not:N \g_@@_backend_int
+    \int_gset_eq:NN \exp_not:N \g_@@_backend_link_int
+      \exp_not:N \g_@@_backend_int
+    \@@_backend:e
+      {
+        bann ~
+        @pdfannot
+        \exp_not:N \int_use:N \exp_not:N \g_@@_backend_link_int
+        \c_space_tl
+        <<
+          /Type /Annot
+          #1
+        >>
+      }
+  }
+\cs_new_protected:Npn \@@_backend_link_end:
+  { \@@_backend:n { eann } }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_last:}
+%   Available using the backend mechanism with a suitably-recent
+%   version.
+%    \begin{macrocode}
+\cs_new:Npn \@@_backend_link_last:
+  { @pdfannot \int_use:N \g_@@_backend_link_int }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_margin:n}
+%   Pass to \texttt{dvipdfmx}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_margin:n #1
+  { \__kernel_backend_literal:e { dvipdfmx:config~g~ \dim_eval:n {#1} } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_on:, \@@_backend_link_off:}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_on:  { \@@_backend:n { link } }
+\cs_new_protected:Npn \@@_backend_link_off: { \@@_backend:n { nolink } }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</dvipdfmx|xetex>
+%    \end{macrocode}
+%
+% \subsection{\texttt{dvisvgm} backend}
+%
+%    \begin{macrocode}
+%<*dvisvgm>
+%    \end{macrocode}
+%
+% \begin{macro}{\@@_backend_generic:nnnn}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_generic:nnnn #1#2#3#4 { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_backend_last:}
+%    \begin{macrocode}
+\cs_new:Npn \@@_backend_last: { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {\@@_backend_link_begin_goto:nnw, \@@_backend_link_begin_user:nnw}
+% \begin{macro}{\@@_backend_link_begin:nnnw}
+% \begin{macro}{\@@_backend_link_end:}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_begin_goto:nnw #1#2 { }
+\cs_new_protected:Npn \@@_backend_link_begin_user:nnw #1#2 { }
+\cs_new_protected:Npn \@@_backend_link_begin:nnnw #1#2#3 { }
+\cs_new_protected:Npn \@@_backend_link_end: { }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_last:}
+%    \begin{macrocode}
+\cs_new:Npe \@@_backend_link_last: { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_margin:n}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_margin:n #1 { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_backend_link_on:, \@@_backend_link_off:}
+%   For handling places like headers.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_link_on:  { }
+\cs_new_protected:Npn \@@_backend_link_off: { }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</dvisvgm>
+%    \end{macrocode}
+%
+% \subsection{Transitional code}
+%
+% This block is temporary: we have moved the backend functions here to a
+% dedicated prefix. To facilitate that, we turn off DocStrip substitution
+% and handle things manually.
+%
+%    \begin{macrocode}
+%<@@=>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\cs_new_eq:NN \__pdf_backend_annotation:nnnn \__pdfannot_backend_generic:nnnn
+\cs_new_eq:NN \__pdf_backend_annotation_last: \__pdfannot_backend_last:
+\clist_map_inline:nn
+  {
+    begin_goto:nnw ,
+    begin_user:nnw ,
+    begin:nnnw     ,
+    end:           ,
+    last:          ,
+    margin:n
+  }
+  { \cs_new_eq:cc { __pdf_backend_link_ #1 } { __pdfannot_backend_link_ #1 } }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdfannot.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend.ins	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/source/latex-dev/l3backend/l3backend.ins	2025-03-11 20:09:53 UTC (rev 74575)
@@ -2,7 +2,7 @@
 
 File l3backend.ins
 
-Copyright (C) 2019-2024 The LaTeX Project
+Copyright (C) 2019-2025 The 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
@@ -35,7 +35,7 @@
 
 \preamble
 
-Copyright (C) 2019-2024 The LaTeX Project
+Copyright (C) 2019-2025 The LaTeX Project
 
 It may be distributed and/or modified under the conditions of
 the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -64,6 +64,7 @@
         \from{l3backend-draw.dtx}    {package,dvipdfmx}
         \from{l3backend-graphics.dtx}{package,dvipdfmx}
         \from{l3backend-pdf.dtx}     {package,dvipdfmx}
+        \from{l3backend-pdfannot.dtx}{package,dvipdfmx}
         \from{l3backend-opacity.dtx} {package,dvipdfmx}
       }
   }
@@ -77,6 +78,7 @@
         \from{l3backend-draw.dtx}    {package,dvips}
         \from{l3backend-graphics.dtx}{package,dvips}
         \from{l3backend-pdf.dtx}     {package,dvips}
+        \from{l3backend-pdfannot.dtx}{package,dvips}
         \from{l3backend-opacity.dtx} {package,dvips}
       }
     \file{l3backend-dvips.pro}
@@ -94,6 +96,7 @@
         \from{l3backend-draw.dtx}    {package,dvisvgm}
         \from{l3backend-graphics.dtx}{package,dvisvgm}
         \from{l3backend-pdf.dtx}     {package,dvisvgm}
+        \from{l3backend-pdfannot.dtx}{package,dvisvgm}
         \from{l3backend-opacity.dtx} {package,dvisvgm}
       }
   }
@@ -107,6 +110,7 @@
         \from{l3backend-draw.dtx}    {package,luatex}
         \from{l3backend-graphics.dtx}{package,luatex}
         \from{l3backend-pdf.dtx}     {package,luatex}
+        \from{l3backend-pdfannot.dtx}{package,luatex}
         \from{l3backend-opacity.dtx} {package,luatex}
       }
   }
@@ -120,6 +124,7 @@
         \from{l3backend-draw.dtx}    {package,pdftex}
         \from{l3backend-graphics.dtx}{package,pdftex}
         \from{l3backend-pdf.dtx}     {package,pdftex}
+        \from{l3backend-pdfannot.dtx}{package,pdftex}
         \from{l3backend-opacity.dtx} {package,pdftex}
       }
   }
@@ -133,6 +138,7 @@
         \from{l3backend-draw.dtx}    {package,xetex}
         \from{l3backend-graphics.dtx}{package,xetex}
         \from{l3backend-pdf.dtx}     {package,xetex}
+        \from{l3backend-pdfannot.dtx}{package,xetex}
         \from{l3backend-opacity.dtx} {package,xetex}
       }
   }
@@ -142,7 +148,7 @@
 \def\MetaPrefix{--}
 \preamble
 
-Copyright (C) 2023,2024 The LaTeX Project
+Copyright (C) 2023-2025 The LaTeX Project
 
 It may be distributed and/or modified under the conditions of
 the LaTeX Project Public License (LPPL), either version 1.3c of

Modified: trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvipdfmx.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvipdfmx.def	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvipdfmx.def	2025-03-11 20:09:53 UTC (rev 74575)
@@ -10,9 +10,10 @@
 %% l3backend-draw.dtx  (with options: `package,dvipdfmx')
 %% l3backend-graphics.dtx  (with options: `package,dvipdfmx')
 %% l3backend-pdf.dtx  (with options: `package,dvipdfmx')
+%% l3backend-pdfannot.dtx  (with options: `package,dvipdfmx')
 %% l3backend-opacity.dtx  (with options: `package,dvipdfmx')
 %% 
-%% Copyright (C) 2019-2024 The LaTeX Project
+%% Copyright (C) 2019-2025 The LaTeX Project
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -26,7 +27,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-dvipdfmx.def}{2024-05-08}{}
+  {l3backend-dvipdfmx.def}{2025-03-10}{}
   {L3 backend support: dvipdfmx}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -306,7 +307,7 @@
   }
 %% File: l3backend-draw.dtx
 \cs_new_eq:NN \__draw_backend_literal:n \__kernel_backend_literal_pdf:n
-\cs_generate_variant:Nn \__draw_backend_literal:n { e }
+\cs_new_eq:NN \__draw_backend_literal:e \__kernel_backend_literal_pdf:e
 \cs_new_protected:Npn \__draw_backend_begin:
   { \__draw_backend_scope_begin: }
 \cs_new_protected:Npn \__draw_backend_end:
@@ -402,12 +403,20 @@
   { \__draw_backend_literal:n { 1 ~ j } }
 \cs_new_protected:Npn \__draw_backend_join_bevel:
   { \__draw_backend_literal:n { 2 ~ j } }
-\cs_new_protected:Npn \__draw_backend_cm:nnnn #1#2#3#4
+\cs_new_protected:Npn \__draw_backend_transform:nnnn #1#2#3#4
   {
-    \__draw_backend_cm_decompose:nnnnN {#1} {#2} {#3} {#4}
-      \__draw_backend_cm_aux:nnnn
+    \str_if_eq:nnTF { #2 ~ #3 } { 0 ~ 0 }
+      {
+        \__kernel_backend_literal:n { x:rotate~0 }
+        \__kernel_backend_literal:n { x:scale~#1~#4 }
+        \__kernel_backend_literal:n { x:rotate~0 }
+      }
+      {
+        \__draw_backend_transform_decompose:nnnnN {#1} {#2} {#3} {#4}
+          \__draw_backend_transform_aux:nnnn
+      }
   }
-\cs_new_protected:Npn \__draw_backend_cm_aux:nnnn #1#2#3#4
+\cs_new_protected:Npn \__draw_backend_transform_aux:nnnn #1#2#3#4
   {
     \__kernel_backend_literal:e
       {
@@ -430,11 +439,16 @@
           { \fp_eval:n { round ( -#4 , 5 ) } }
       }
   }
-\cs_new_protected:Npn \__draw_backend_cm_decompose:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \__draw_backend_shift:nn #1#2
   {
+    \__draw_backend_literal:n
+      { 1 ~ 0 ~ 0 ~ 1 ~ #1 ~ #2 ~ cm }
+  }
+\cs_new_protected:Npn \__draw_backend_transform_decompose:nnnnN #1#2#3#4#5
+  {
     \use:e
       {
-        \__draw_backend_cm_decompose_auxi:nnnnN
+        \__draw_backend_transform_decompose_auxi:nnnnN
           { \fp_eval:n { (#1 + #4) / 2 } }
           { \fp_eval:n { (#1 - #4) / 2 } }
           { \fp_eval:n { (#3 + #2) / 2 } }
@@ -442,11 +456,11 @@
       }
         #5
   }
-\cs_new_protected:Npn \__draw_backend_cm_decompose_auxi:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \__draw_backend_transform_decompose_auxi:nnnnN #1#2#3#4#5
   {
     \use:e
       {
-        \__draw_backend_cm_decompose_auxii:nnnnN
+        \__draw_backend_transform_decompose_auxii:nnnnN
           { \fp_eval:n { 2 * sqrt ( #1 * #1 + #4 * #4 ) } }
           { \fp_eval:n { 2 * sqrt ( #2 * #2 + #3 * #3 ) } }
           { \fp_eval:n { atand ( #3 , #2 ) } }
@@ -454,11 +468,11 @@
       }
         #5
   }
-\cs_new_protected:Npn \__draw_backend_cm_decompose_auxii:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \__draw_backend_transform_decompose_auxii:nnnnN #1#2#3#4#5
   {
     \use:e
       {
-        \__draw_backend_cm_decompose_auxiii:nnnnN
+        \__draw_backend_transform_decompose_auxiii:nnnnN
           { \fp_eval:n { ( #4 - #3 ) / 2 } }
           { \fp_eval:n { ( #1 + #2 ) / 2 } }
           { \fp_eval:n { ( #1 - #2 ) / 2 } }
@@ -466,7 +480,7 @@
       }
         #5
   }
-\cs_new_protected:Npn \__draw_backend_cm_decompose_auxiii:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \__draw_backend_transform_decompose_auxiii:nnnnN #1#2#3#4#5
   {
     \fp_compare:nNnTF { abs( #2 ) } > { abs ( #3 ) }
       { #5 {#1} {#2} {#3} {#4} }
@@ -599,7 +613,6 @@
 \__graphics_backend_loaded:n
   { \cs_new_eq:NN \__graphics_backend_get_pagecount:n \__graphics_get_pagecount:n }
 %% File: l3backend-pdf.dtx
-\box_new:N \l__pdf_internal_box
 \cs_new_protected:Npe \__pdf_backend:n #1
   { \__kernel_backend_literal:n { pdf: #1 } }
 \cs_generate_variant:Nn \__pdf_backend:n { e }
@@ -652,48 +665,6 @@
   { @pdf.obj \int_use:N \g__pdf_backend_object_int }
 \cs_new:Npn \__pdf_backend_pageobject_ref:n #1
   { @page #1 }
-\int_new:N \g__pdf_backend_annotation_int
-\cs_new_protected:Npn \__pdf_backend_annotation:nnnn #1#2#3#4
-  {
-    \int_gincr:N \g__pdf_backend_object_int
-    \int_gset_eq:NN \g__pdf_backend_annotation_int \g__pdf_backend_object_int
-    \__pdf_backend:e
-      {
-        ann ~ @pdf.obj \int_use:N \g__pdf_backend_object_int \c_space_tl
-        width  ~ \dim_eval:n {#1} ~
-        height ~ \dim_eval:n {#2} ~
-        depth  ~ \dim_eval:n {#3} ~
-        << /Type /Annot #4 >>
-      }
-  }
-\cs_new:Npn \__pdf_backend_annotation_last:
-  { @pdf.obj \int_use:N \g__pdf_backend_annotation_int }
-\int_new:N \g__pdf_backend_link_int
-\cs_new_protected:Npn \__pdf_backend_link_begin_goto:nnw #1#2
-  { \__pdf_backend_link_begin:n { #1 /Subtype /Link /A << /S /GoTo /D ( #2 ) >> } }
-\cs_new_protected:Npn \__pdf_backend_link_begin_user:nnw #1#2
-  { \__pdf_backend_link_begin:n {#1#2} }
-\cs_new_protected:Npe \__pdf_backend_link_begin:n #1
-  {
-    \exp_not:N \int_gincr:N \exp_not:N  \g__pdf_backend_link_int
-    \__pdf_backend:e
-      {
-        bann ~
-        @pdf.lnk
-        \exp_not:N \int_use:N \exp_not:N  \g__pdf_backend_link_int
-        \c_space_tl
-        <<
-          /Type /Annot
-          #1
-        >>
-      }
-  }
-\cs_new_protected:Npn \__pdf_backend_link_end:
-  { \__pdf_backend:n { eann } }
-\cs_new:Npn \__pdf_backend_link_last:
-  { @pdf.lnk \int_use:N \g__pdf_backend_link_int }
-\cs_new_protected:Npn \__pdf_backend_link_margin:n #1
-  { \__kernel_backend_literal:e { dvipdfmx:config~g~ \dim_eval:n {#1} } }
 \cs_new_protected:Npn \__pdf_backend_destination:nn #1#2
   {
     \__pdf_backend:e
@@ -789,6 +760,70 @@
           }
       }
   }
+%% File: l3backend-pdfannot.dtx
+\cs_new_protected:Npe \__pdfannot_backend:n #1
+  { \__kernel_backend_literal:n { pdf: #1 } }
+\cs_generate_variant:Nn \__pdfannot_backend:n { e }
+\int_new:N \g__pdfannot_backend_int
+\cs_new_protected:Npn \__pdfannot_backend_generic:nnnn #1#2#3#4
+  {
+    \int_gincr:N \g__pdfannot_backend_int
+    \__pdfannot_backend:e
+      {
+        ann ~ @pdfannot \int_use:N \g__pdfannot_backend_int \c_space_tl
+        width  ~ \dim_eval:n {#1} ~
+        height ~ \dim_eval:n {#2} ~
+        depth  ~ \dim_eval:n {#3} ~
+        << /Type /Annot #4 >>
+      }
+  }
+\cs_new:Npn \__pdfannot_backend_last:
+  { @pdfannot \int_use:N \g__pdfannot_backend_int }
+\int_new:N \g__pdfannot_backend_link_int
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_goto:nnw #1#2
+  {
+    \__pdfannot_backend_link_begin:n
+      { #1 /Subtype /Link /A << /S /GoTo /D ( #2 ) >> }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_user:nnw #1#2
+  { \__pdfannot_backend_link_begin:n {#1#2} }
+\cs_new_protected:Npe \__pdfannot_backend_link_begin:n #1
+  {
+    \int_gincr:N \exp_not:N \g__pdfannot_backend_int
+    \int_gset_eq:NN \exp_not:N \g__pdfannot_backend_link_int
+      \exp_not:N \g__pdfannot_backend_int
+    \__pdfannot_backend:e
+      {
+        bann ~
+        @pdfannot
+        \exp_not:N \int_use:N \exp_not:N \g__pdfannot_backend_link_int
+        \c_space_tl
+        <<
+          /Type /Annot
+          #1
+        >>
+      }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_end:
+  { \__pdfannot_backend:n { eann } }
+\cs_new:Npn \__pdfannot_backend_link_last:
+  { @pdfannot \int_use:N \g__pdfannot_backend_link_int }
+\cs_new_protected:Npn \__pdfannot_backend_link_margin:n #1
+  { \__kernel_backend_literal:e { dvipdfmx:config~g~ \dim_eval:n {#1} } }
+\cs_new_protected:Npn \__pdfannot_backend_link_on:  { \__pdfannot_backend:n { link } }
+\cs_new_protected:Npn \__pdfannot_backend_link_off: { \__pdfannot_backend:n { nolink } }
+\cs_new_eq:NN \__pdf_backend_annotation:nnnn \__pdfannot_backend_generic:nnnn
+\cs_new_eq:NN \__pdf_backend_annotation_last: \__pdfannot_backend_last:
+\clist_map_inline:nn
+  {
+    begin_goto:nnw ,
+    begin_user:nnw ,
+    begin:nnnw     ,
+    end:           ,
+    last:          ,
+    margin:n
+  }
+  { \cs_new_eq:cc { __pdf_backend_link_ #1 } { __pdfannot_backend_link_ #1 } }
 %% File: l3backend-opacity.dtx
 \bool_lazy_and:nnT
   { \cs_if_exist_p:N \pdfmanagement_if_active_p: }

Modified: trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.def	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.def	2025-03-11 20:09:53 UTC (rev 74575)
@@ -10,9 +10,10 @@
 %% l3backend-draw.dtx  (with options: `package,dvips')
 %% l3backend-graphics.dtx  (with options: `package,dvips')
 %% l3backend-pdf.dtx  (with options: `package,dvips')
+%% l3backend-pdfannot.dtx  (with options: `package,dvips')
 %% l3backend-opacity.dtx  (with options: `package,dvips')
 %% 
-%% Copyright (C) 2019-2024 The LaTeX Project
+%% Copyright (C) 2019-2025 The LaTeX Project
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -26,7 +27,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-dvips.def}{2024-05-08}{}
+  {l3backend-dvips.def}{2025-03-10}{}
   {L3 backend support: dvips}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -553,11 +554,16 @@
   { \__draw_backend_literal:n { 1 ~ setlinejoin } }
 \cs_new_protected:Npn \__draw_backend_join_bevel:
   { \__draw_backend_literal:n { 2 ~ setlinejoin } }
-\cs_new_protected:Npn \__draw_backend_cm:nnnn #1#2#3#4
+\cs_new_protected:Npn \__draw_backend_transform:nnnn #1#2#3#4
   {
     \__draw_backend_literal:n
       { [ #1 ~ #2 ~ #3 ~ #4 ~ 0 ~ 0 ] ~ concat }
   }
+\cs_new_protected:Npn \__draw_backend_shift:nn #1#2
+  {
+    \__draw_backend_literal:n
+      { [ 1 ~ 0 ~ 0 ~ 1 ~ #1 ~ #2 ] ~ concat }
+  }
 \cs_new_protected:Npn \__draw_backend_box_use:Nnnnn #1#2#3#4#5
   {
     \__draw_backend_literal:n { save }
@@ -569,9 +575,9 @@
     \__draw_backend_literal:n { save }
     \__draw_backend_literal:n { currentpoint }
     \__draw_backend_literal:n { currentpoint~translate }
-    \__draw_backend_cm:nnnn { 1 } { 0 } { 0 } { -1 }
-    \__draw_backend_cm:nnnn {#2} {#3} {#4} {#5}
-    \__draw_backend_cm:nnnn { 1 } { 0 } { 0 } { -1 }
+    \__draw_backend_transform:nnnn { 1 } { 0 } { 0 } { -1 }
+    \__draw_backend_transform:nnnn {#2} {#3} {#4} {#5}
+    \__draw_backend_transform:nnnn { 1 } { 0 } { 0 } { -1 }
     \__draw_backend_literal:n { neg~exch~neg~exch~translate }
     \__draw_backend_literal:n { [end] }
     \hbox_overlap_right:n { \box_use:N #1 }
@@ -615,7 +621,6 @@
 \__graphics_backend_loaded:n
   { \cs_new_eq:NN \__graphics_backend_get_pagecount:n \__graphics_get_pagecount:n }
 %% File: l3backend-pdf.dtx
-\box_new:N \l__pdf_internal_box
 \cs_new_protected:Npn \__pdf_backend_pdfmark:n #1
   { \__kernel_backend_postscript:n { mark #1 ~ pdfmark } }
 \cs_generate_variant:Nn \__pdf_backend_pdfmark:n { e }
@@ -701,218 +706,6 @@
   { { pdf.obj \int_use:N \g__pdf_backend_object_int } }
 \cs_new:Npn \__pdf_backend_pageobject_ref:n #1
   { { Page #1 } }
-\box_new:N \l__pdf_backend_content_box
-\box_new:N \l__pdf_backend_model_box
-\int_new:N \g__pdf_backend_annotation_int
-\cs_new_protected:Npn \__pdf_backend_annotation:nnnn #1#2#3#4
-  {
-    \exp_args:Nf \__pdf_backend_annotation_aux:nnnn
-      { \dim_eval:n {#1} } {#2} {#3} {#4}
-  }
-\cs_new_protected:Npn \__pdf_backend_annotation_aux:nnnn #1#2#3#4
-  {
-    \box_move_down:nn {#3}
-      { \hbox:n { \__kernel_backend_postscript:n { pdf.save.ll } } }
-    \box_move_up:nn {#2}
-      {
-        \hbox:n
-          {
-            \__kernel_kern:n {#1}
-            \__kernel_backend_postscript:n { pdf.save.ur }
-            \__kernel_kern:n { -#1 }
-          }
-      }
-    \int_gincr:N \g__pdf_backend_object_int
-    \int_gset_eq:NN \g__pdf_backend_annotation_int \g__pdf_backend_object_int
-    \__pdf_backend_pdfmark:e
-      {
-        /_objdef { pdf.obj \int_use:N \g__pdf_backend_object_int }
-        pdf.rect
-        #4 ~
-        /ANN
-      }
-  }
-\cs_new:Npn \__pdf_backend_annotation_last:
-  { { pdf.obj \int_use:N \g__pdf_backend_annotation_int } }
-\int_new:N \g__pdf_backend_link_int
-\tl_new:N \g__pdf_backend_link_dict_tl
-\int_new:N \g__pdf_backend_link_sf_int
-\bool_new:N \g__pdf_backend_link_math_bool
-\bool_new:N \g__pdf_backend_link_bool
-\tl_new:N \l__pdf_breaklink_pdfmark_tl
-\tl_set:Nn \l__pdf_breaklink_pdfmark_tl { pdfmark }
-\cs_new_protected:Npn \__pdf_breaklink_postscript:n #1 { }
-\cs_new_eq:NN \__pdf_breaklink_usebox:N \box_use:N
-\cs_new_protected:Npn \__pdf_backend_link_begin_goto:nnw #1#2
-  {
-    \__pdf_backend_link_begin:nw
-      { #1 /Subtype /Link /Action << /S /GoTo /D ( #2 ) >> }
-  }
-\cs_new_protected:Npn \__pdf_backend_link_begin_user:nnw #1#2
-  { \__pdf_backend_link_begin:nw {#1#2} }
-\cs_new_protected:Npn \__pdf_backend_link_begin:nw #1
-  {
-    \bool_if:NF \g__pdf_backend_link_bool
-      { \__pdf_backend_link_begin_aux:nw {#1} }
-  }
-\cs_new_protected:Npn \__pdf_backend_link_begin_aux:nw #1
-  {
-    \bool_gset_true:N \g__pdf_backend_link_bool
-    \__kernel_backend_postscript:n
-      { /pdf.link.dict ( #1 ) def }
-    \tl_gset:Nn \g__pdf_backend_link_dict_tl {#1}
-    \__pdf_backend_link_sf_save:
-    \mode_if_math:TF
-      { \bool_gset_true:N \g__pdf_backend_link_math_bool }
-      { \bool_gset_false:N \g__pdf_backend_link_math_bool }
-    \hbox_set:Nw \l__pdf_backend_content_box
-      \__pdf_backend_link_sf_restore:
-      \bool_if:NT \g__pdf_backend_link_math_bool
-        { \c_math_toggle_token }
-  }
-\cs_new_protected:Npn \__pdf_backend_link_end:
-  {
-    \bool_if:NT \g__pdf_backend_link_bool
-      { \__pdf_backend_link_end_aux: }
-  }
-\cs_new_protected:Npn \__pdf_backend_link_end_aux:
-  {
-      \bool_if:NT \g__pdf_backend_link_math_bool
-        { \c_math_toggle_token }
-      \__pdf_backend_link_sf_save:
-    \hbox_set_end:
-    \__pdf_backend_link_minima:
-    \hbox_set:Nn \l__pdf_backend_model_box { Gg }
-    \exp_args:Ne \__pdf_backend_link_outerbox:n
-      {
-        \int_if_odd:nTF { \value { page } }
-          { \oddsidemargin }
-          { \evensidemargin }
-      }
-    \box_move_down:nn { \box_dp:N \l__pdf_backend_content_box }
-      { \hbox:n { \__kernel_backend_postscript:n { pdf.save.linkll } } }
-    \__pdf_breaklink_postscript:n { pdf.bordertracking.begin }
-    \__pdf_breaklink_usebox:N \l__pdf_backend_content_box
-    \__pdf_breaklink_postscript:n { pdf.bordertracking.end }
-    \box_move_up:nn { \box_ht:N \l__pdf_backend_content_box }
-      {
-        \hbox:n
-          { \__kernel_backend_postscript:n { pdf.save.linkur } }
-      }
-    \int_gincr:N \g__pdf_backend_object_int
-    \int_gset_eq:NN \g__pdf_backend_link_int \g__pdf_backend_object_int
-    \__kernel_backend_postscript:e
-      {
-        mark
-        /_objdef { pdf.obj \int_use:N \g__pdf_backend_link_int }
-        \g__pdf_backend_link_dict_tl \c_space_tl
-        pdf.rect
-        /ANN ~ \l__pdf_breaklink_pdfmark_tl
-      }
-    \__pdf_backend_link_sf_restore:
-    \bool_gset_false:N \g__pdf_backend_link_bool
-  }
-\cs_new_protected:Npn \__pdf_backend_link_minima:
-  {
-    \hbox_set:Nn \l__pdf_backend_model_box { Gg }
-    \__kernel_backend_postscript:e
-      {
-        /pdf.linkdp.pad ~
-          \dim_to_decimal:n
-            {
-              \dim_max:nn
-                {
-                    \box_dp:N \l__pdf_backend_model_box
-                  - \box_dp:N \l__pdf_backend_content_box
-                }
-                { 0pt }
-            } ~
-              pdf.pt.dvi ~ def
-        /pdf.linkht.pad ~
-          \dim_to_decimal:n
-            {
-              \dim_max:nn
-                {
-                    \box_ht:N \l__pdf_backend_model_box
-                  - \box_ht:N \l__pdf_backend_content_box
-                }
-                { 0pt }
-            } ~
-              pdf.pt.dvi ~ def
-      }
-  }
-\cs_new_protected:Npn \__pdf_backend_link_outerbox:n #1
-  {
-    \__kernel_backend_postscript:e
-      {
-        /pdf.outerbox
-          [
-            \dim_to_decimal:n {#1} ~
-            \dim_to_decimal:n { -\box_dp:N \l__pdf_backend_model_box } ~
-            \dim_to_decimal:n { #1 + \textwidth } ~
-            \dim_to_decimal:n { \box_ht:N \l__pdf_backend_model_box }
-          ]
-          [ exch { pdf.pt.dvi } forall ] def
-        /pdf.baselineskip ~
-          \dim_to_decimal:n { \tex_baselineskip:D } ~ dup ~ 0 ~ gt
-            { pdf.pt.dvi ~ def }
-            { pop ~ pop }
-          ifelse
-      }
-  }
-\cs_new_protected:Npn \__pdf_backend_link_sf_save:
-  {
-    \int_gset:Nn \g__pdf_backend_link_sf_int
-      {
-        \mode_if_horizontal:TF
-          { \tex_spacefactor:D }
-          { 0 }
-      }
-  }
-\cs_new_protected:Npn \__pdf_backend_link_sf_restore:
-  {
-    \mode_if_horizontal:T
-      {
-        \int_compare:nNnT \g__pdf_backend_link_sf_int > { 0 }
-          { \int_set_eq:NN \tex_spacefactor:D \g__pdf_backend_link_sf_int }
-      }
-  }
-\use_none:n
-  {
-    \cs_if_exist:NT \@makecol at hook
-      {
-        \tl_put_right:Nn \@makecol at hook
-          {
-            \box_if_empty:NF \l_shipout_box
-              {
-                \vbox_set:Nn \l_shipout_box
-                  {
-                    \__kernel_backend_postscript:n
-                      {
-                        pdf.globaldict /pdf.brokenlink.rect ~ known
-                          { pdf.bordertracking.continue }
-                        if
-                      }
-                    \vbox_unpack_drop:N \l_shipout_box
-                    \__kernel_backend_postscript:n
-                      { pdf.bordertracking.endpage }
-                  }
-              }
-          }
-        \tl_set:Nn \l__pdf_breaklink_pdfmark_tl { pdf.pdfmark }
-        \cs_set_eq:NN \__pdf_breaklink_postscript:n \__kernel_backend_postscript:n
-        \cs_set_eq:NN \__pdf_breaklink_usebox:N \hbox_unpack:N
-      }
-  }
-\cs_new:Npn \__pdf_backend_link_last:
-  { { pdf.obj \int_use:N \g__pdf_backend_link_int } }
-\cs_new_protected:Npn \__pdf_backend_link_margin:n #1
-  {
-    \__kernel_backend_postscript:e
-      {
-        /pdf.linkmargin { \dim_to_decimal:n {#1} ~ pdf.pt.dvi } def
-      }
-  }
 \cs_new_protected:Npn \__pdf_backend_destination:nn #1#2
   {
     \__kernel_backend_postscript:n { pdf.dest.anchor }
@@ -1020,6 +813,233 @@
           }
       }
   }
+%% File: l3backend-pdfannot.dtx
+\box_new:N \l__pdfannot_backend_content_box
+\box_new:N \l__pdfannot_backend_model_box
+\int_new:N \g__pdfannot_backend_int
+\cs_new_protected:Npn \__pdfannot_backend_generic:nnnn #1#2#3#4
+  {
+    \exp_args:Nf \__pdfannot_backend_generic_aux:nnnn
+      { \dim_eval:n {#1} } {#2} {#3} {#4}
+  }
+\cs_new_protected:Npn \__pdfannot_backend_generic_aux:nnnn #1#2#3#4
+  {
+    \box_move_down:nn {#3}
+      { \hbox:n { \__kernel_backend_postscript:n { pdfannot.save.ll } } }
+    \box_move_up:nn {#2}
+      {
+        \hbox:n
+          {
+            \__kernel_kern:n {#1}
+            \__kernel_backend_postscript:n { pdfannot.save.ur }
+            \__kernel_kern:n { -#1 }
+          }
+      }
+    \int_gincr:N \g__pdfannot_backend_int
+    \__kernel_backend_postscript:e
+      {
+        mark
+        /_objdef { pdfannot \int_use:N \g__pdfannot_backend_int }
+        pdfannot.rect
+        #4 ~
+        /ANN ~
+        pdfmark
+      }
+  }
+\cs_new:Npn \__pdfannot_backend_last:
+  { { pdfannot \int_use:N \g__pdfannot_backend_int } }
+\int_new:N \g__pdfannot_backend_link_int
+\tl_new:N \g__pdfannot_backend_link_dict_tl
+\int_new:N \g__pdfannot_backend_link_sf_int
+\bool_new:N \g__pdfannot_backend_link_math_bool
+\bool_new:N \g__pdfannot_backend_link_bool
+\tl_new:N \l__pdfannot_backend_breaklink_pdfmark_tl
+\tl_set:Nn \l__pdfannot_backend_breaklink_pdfmark_tl { pdfmark }
+\cs_new_protected:Npn \__pdfannot_backend_breaklink_postscript:n #1 { }
+\cs_new_eq:NN \__pdfannot_backend_breaklink_usebox:N \box_use:N
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_goto:nnw #1#2
+  {
+    \__pdfannot_backend_link_begin:nw
+      { #1 /Subtype /Link /Action << /S /GoTo /D ( #2 ) >> }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_user:nnw #1#2
+  { \__pdfannot_backend_link_begin:nw {#1#2} }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin:nw #1
+  {
+    \bool_if:NF \g__pdfannot_backend_link_bool
+      { \__pdfannot_backend_link_begin_aux:nw {#1} }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_aux:nw #1
+  {
+    \bool_gset_true:N \g__pdfannot_backend_link_bool
+    \__kernel_backend_postscript:n
+      { /pdfannot.link.dict ( #1 ) def }
+    \tl_gset:Nn \g__pdfannot_backend_link_dict_tl {#1}
+    \__pdfannot_backend_link_sf_save:
+    \mode_if_math:TF
+      { \bool_gset_true:N \g__pdfannot_backend_link_math_bool }
+      { \bool_gset_false:N \g__pdfannot_backend_link_math_bool }
+    \hbox_set:Nw \l__pdfannot_backend_content_box
+      \__pdfannot_backend_link_sf_restore:
+      \bool_if:NT \g__pdfannot_backend_link_math_bool
+        { \c_math_toggle_token }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_end:
+  {
+    \bool_if:NT \g__pdfannot_backend_link_bool
+      { \__pdfannot_backend_link_end_aux: }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_end_aux:
+  {
+      \bool_if:NT \g__pdfannot_backend_link_math_bool
+        { \c_math_toggle_token }
+      \__pdfannot_backend_link_sf_save:
+    \hbox_set_end:
+    \__pdfannot_backend_link_minima:
+    \hbox_set:Nn \l__pdfannot_backend_model_box { Gg }
+    \exp_args:Ne \__pdfannot_backend_link_outerbox:n
+      {
+        \int_if_odd:nTF { \value { page } }
+          { \oddsidemargin }
+          { \evensidemargin }
+      }
+    \box_move_down:nn { \box_dp:N \l__pdfannot_backend_content_box }
+      { \hbox:n { \__kernel_backend_postscript:n { pdfannot.save.linkll } } }
+    \__pdfannot_backend_breaklink_postscript:n { pdfannot.bordertracking.begin }
+    \__pdfannot_backend_breaklink_usebox:N \l__pdfannot_backend_content_box
+    \__pdfannot_backend_breaklink_postscript:n { pdfannot.bordertracking.end }
+    \box_move_up:nn { \box_ht:N \l__pdfannot_backend_content_box }
+      {
+        \hbox:n
+          { \__kernel_backend_postscript:n { pdfannot.save.linkur } }
+      }
+    \int_gincr:N \g__pdfannot_backend_int
+    \int_gset_eq:NN \g__pdfannot_backend_link_int \g__pdfannot_backend_int
+    \__kernel_backend_postscript:e
+      {
+        mark
+        /_objdef { pdfannot \int_use:N \g__pdfannot_backend_link_int }
+        \g__pdfannot_backend_link_dict_tl \c_space_tl
+        pdfannot.rect
+        /ANN ~ \l__pdfannot_backend_breaklink_pdfmark_tl
+      }
+    \__pdfannot_backend_link_sf_restore:
+    \bool_gset_false:N \g__pdfannot_backend_link_bool
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_minima:
+  {
+    \hbox_set:Nn \l__pdfannot_backend_model_box { Gg }
+    \__kernel_backend_postscript:e
+      {
+        /pdfannot.linkdp.pad ~
+          \dim_to_decimal:n
+            {
+              \dim_max:nn
+                {
+                    \box_dp:N \l__pdfannot_backend_model_box
+                  - \box_dp:N \l__pdfannot_backend_content_box
+                }
+                { 0pt }
+            } ~
+              pdfannot.pt.dvi ~ def
+        /pdfannot.linkht.pad ~
+          \dim_to_decimal:n
+            {
+              \dim_max:nn
+                {
+                    \box_ht:N \l__pdfannot_backend_model_box
+                  - \box_ht:N \l__pdfannot_backend_content_box
+                }
+                { 0pt }
+            } ~
+              pdfannot.pt.dvi ~ def
+      }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_outerbox:n #1
+  {
+    \__kernel_backend_postscript:e
+      {
+        /pdfannot.outerbox
+          [
+            \dim_to_decimal:n {#1} ~
+            \dim_to_decimal:n { -\box_dp:N \l__pdfannot_backend_model_box } ~
+            \dim_to_decimal:n { #1 + \textwidth } ~
+            \dim_to_decimal:n { \box_ht:N \l__pdfannot_backend_model_box }
+          ]
+          [ exch { pdfannot.pt.dvi } forall ] def
+        /pdfannot.baselineskip ~
+          \dim_to_decimal:n { \tex_baselineskip:D } ~ dup ~ 0 ~ gt
+            { pdfannot.pt.dvi ~ def }
+            { pop ~ pop }
+          ifelse
+      }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_sf_save:
+  {
+    \int_gset:Nn \g__pdfannot_backend_link_sf_int
+      {
+        \mode_if_horizontal:TF
+          { \tex_spacefactor:D }
+          { 0 }
+      }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_sf_restore:
+  {
+    \mode_if_horizontal:T
+      {
+        \int_compare:nNnT \g__pdfannot_backend_link_sf_int > { 0 }
+          { \int_set:Nn \tex_spacefactor:D \g__pdfannot_backend_link_sf_int }
+      }
+  }
+\use_none:nnn
+\cs_if_exist:NT \hook_gput_code:nnn
+  {
+    \hook_gput_code:nnn { build/column/after } { backend }
+      {
+        \box_if_empty:NF \l_shipout_box
+          {
+            \vbox_set:Nn \l_shipout_box
+              {
+                \__kernel_backend_postscript:n
+                  {
+                    pdfannot.globaldict /pdfannot.brokenlink.rect ~ known
+                      { pdfannot.bordertracking.continue }
+                    if
+                  }
+                \vbox_unpack_drop:N \l_shipout_box
+                \__kernel_backend_postscript:n
+                  { pdfannot.bordertracking.endpage }
+              }
+          }
+      }
+    \tl_set:Nn \l__pdfannot_backend_breaklink_pdfmark_tl { pdfannot.pdfmark }
+    \cs_set_eq:NN \__pdfannot_backend_breaklink_postscript:n
+      \__kernel_backend_postscript:n
+    \cs_set_eq:NN \__pdfannot_backend_breaklink_usebox:N \hbox_unpack:N
+  }
+\cs_new:Npn \__pdfannot_backend_link_last:
+  { { pdfannot.annot \int_use:N \g__pdfannot_backend_link_int } }
+\cs_new_protected:Npn \__pdfannot_backend_link_margin:n #1
+  {
+    \__kernel_backend_postscript:e
+      {
+        /pdfannot.linkmargin { \dim_to_decimal:n {#1} ~ pdfannot.pt.dvi } def
+      }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_on:  { }
+\cs_new_protected:Npn \__pdfannot_backend_link_off: { }
+\cs_new_eq:NN \__pdf_backend_annotation:nnnn \__pdfannot_backend_generic:nnnn
+\cs_new_eq:NN \__pdf_backend_annotation_last: \__pdfannot_backend_last:
+\clist_map_inline:nn
+  {
+    begin_goto:nnw ,
+    begin_user:nnw ,
+    begin:nnnw     ,
+    end:           ,
+    last:          ,
+    margin:n
+  }
+  { \cs_new_eq:cc { __pdf_backend_link_ #1 } { __pdfannot_backend_link_ #1 } }
 %% File: l3backend-opacity.dtx
 \cs_new_protected:Npn \__opacity_backend_select:n #1
   {

Modified: trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.pro
===================================================================
--- trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.pro	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.pro	2025-03-11 20:09:53 UTC (rev 74575)
@@ -6,7 +6,7 @@
 %%
 %% l3backend-header.dtx  (with options: `header,dvips')
 %% 
-%% Copyright (C) 2019-2024 The LaTeX Project
+%% Copyright (C) 2019-2025 The LaTeX Project
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of

Modified: trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvisvgm.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvisvgm.def	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvisvgm.def	2025-03-11 20:09:53 UTC (rev 74575)
@@ -10,9 +10,10 @@
 %% l3backend-draw.dtx  (with options: `package,dvisvgm')
 %% l3backend-graphics.dtx  (with options: `package,dvisvgm')
 %% l3backend-pdf.dtx  (with options: `package,dvisvgm')
+%% l3backend-pdfannot.dtx  (with options: `package,dvisvgm')
 %% l3backend-opacity.dtx  (with options: `package,dvisvgm')
 %% 
-%% Copyright (C) 2019-2024 The LaTeX Project
+%% Copyright (C) 2019-2025 The LaTeX Project
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -26,7 +27,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-dvisvgm.def}{2024-05-08}{}
+  {l3backend-dvisvgm.def}{2025-03-10}{}
   {L3 backend support: dvisvgm}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -439,7 +440,7 @@
   { \__kernel_backend_scope:n { stroke-linejoin="round" } }
 \cs_new_protected:Npn \__draw_backend_join_bevel:
   { \__kernel_backend_scope:n { stroke-linejoin="bevel" } }
-\cs_new_protected:Npn \__draw_backend_cm:nnnn #1#2#3#4
+\cs_new_protected:Npn \__draw_backend_transform:nnnn #1#2#3#4
   {
     \__kernel_backend_scope:n
       {
@@ -447,10 +448,18 @@
           " matrix ( #1 , #2 , #3 , #4 , 0pt , 0pt ) "
       }
   }
+\cs_new_protected:Npn \__draw_backend_shift:nn #1#2
+  {
+    \__kernel_backend_scope:n
+      {
+        transform =
+          " matrix ( 1 , 0 , 0 , 1 ,  #1pt , #2pt ) "
+      }
+  }
 \cs_new_protected:Npn \__draw_backend_box_use:Nnnnn #1#2#3#4#5
   {
     \__kernel_backend_scope_begin:
-    \__draw_backend_cm:nnnn {#2} {#3} {#4} {#5}
+    \__draw_backend_transform:nnnn {#2} {#3} {#4} {#5}
     \__kernel_backend_literal_svg:n
       {
         < g~
@@ -621,14 +630,6 @@
 \__graphics_backend_loaded:n
   { \cs_new_eq:NN \__graphics_backend_get_pagecount:n \__graphics_get_pagecount:n }
 %% File: l3backend-pdf.dtx
-\cs_new_protected:Npn \__pdf_backend_annotation:nnnn #1#2#3#4 { }
-\cs_new:Npn \__pdf_backend_annotation_last: { }
-\cs_new_protected:Npn \__pdf_backend_link_begin_goto:nnw #1#2 { }
-\cs_new_protected:Npn \__pdf_backend_link_begin_user:nnw #1#2 { }
-\cs_new_protected:Npn \__pdf_backend_link_begin:nnnw #1#2#3 { }
-\cs_new_protected:Npn \__pdf_backend_link_end: { }
-\cs_new:Npe \__pdf_backend_link_last: { }
-\cs_new_protected:Npn \__pdf_backend_link_margin:n #1 { }
 \cs_new_protected:Npn \__pdf_backend_destination:nn #1#2 { }
 \cs_new_protected:Npn \__pdf_backend_destination:nnnn #1#2#3#4 { }
 \cs_new_protected:Npn \__pdf_backend_catalog_gput:nn #1#2 { }
@@ -651,6 +652,29 @@
 \cs_new_protected:Npn \__pdf_backend_bdc:nn #1#2 { }
 \cs_new_protected:Npn \__pdf_backend_emc: { }
 \cs_new_protected:Npn \__pdf_backend_pagesize_gset:nn #1#2 { }
+%% File: l3backend-pdfannot.dtx
+\cs_new_protected:Npn \__pdfannot_backend_generic:nnnn #1#2#3#4 { }
+\cs_new:Npn \__pdfannot_backend_last: { }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_goto:nnw #1#2 { }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_user:nnw #1#2 { }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin:nnnw #1#2#3 { }
+\cs_new_protected:Npn \__pdfannot_backend_link_end: { }
+\cs_new:Npe \__pdfannot_backend_link_last: { }
+\cs_new_protected:Npn \__pdfannot_backend_link_margin:n #1 { }
+\cs_new_protected:Npn \__pdfannot_backend_link_on:  { }
+\cs_new_protected:Npn \__pdfannot_backend_link_off: { }
+\cs_new_eq:NN \__pdf_backend_annotation:nnnn \__pdfannot_backend_generic:nnnn
+\cs_new_eq:NN \__pdf_backend_annotation_last: \__pdfannot_backend_last:
+\clist_map_inline:nn
+  {
+    begin_goto:nnw ,
+    begin_user:nnw ,
+    begin:nnnw     ,
+    end:           ,
+    last:          ,
+    margin:n
+  }
+  { \cs_new_eq:cc { __pdf_backend_link_ #1 } { __pdfannot_backend_link_ #1 } }
 %% File: l3backend-opacity.dtx
 \cs_new_protected:Npn \__opacity_backend_select:n #1
   { \__opacity_backend:nn {#1} { } }

Modified: trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.def	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.def	2025-03-11 20:09:53 UTC (rev 74575)
@@ -10,9 +10,10 @@
 %% l3backend-draw.dtx  (with options: `package,luatex')
 %% l3backend-graphics.dtx  (with options: `package,luatex')
 %% l3backend-pdf.dtx  (with options: `package,luatex')
+%% l3backend-pdfannot.dtx  (with options: `package,luatex')
 %% l3backend-opacity.dtx  (with options: `package,luatex')
 %% 
-%% Copyright (C) 2019-2024 The LaTeX Project
+%% Copyright (C) 2019-2025 The LaTeX Project
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -26,7 +27,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-luatex.def}{2024-05-08}{}
+  {l3backend-luatex.def}{2025-03-10}{}
   {L3 backend support: PDF output (LuaTeX)}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -60,7 +61,11 @@
     \tex_pdfextension:D literal
       { \exp_not:n {#1} }
   }
-\cs_generate_variant:Nn \__kernel_backend_literal_pdf:n { e }
+\cs_new_protected:Npn \__kernel_backend_literal_pdf:e #1
+  {
+    \tex_pdfextension:D literal
+      {#1}
+  }
 \cs_new_protected:Npn \__kernel_backend_literal_page:n #1
   {
     \tex_pdfextension:D literal ~
@@ -84,7 +89,11 @@
     \tex_pdfextension:D setmatrix
         { \exp_not:n {#1} }
   }
-\cs_generate_variant:Nn \__kernel_backend_matrix:n { e }
+\cs_new_protected:Npn \__kernel_backend_matrix:e #1
+  {
+    \tex_pdfextension:D setmatrix
+        {#1}
+  }
 %% File: l3backend-color.dtx
 \int_new:N \l__color_backend_stack_int
 \cs_new_protected:Npn \__kernel_color_backend_stack_init:Nnn #1#2#3
@@ -384,7 +393,7 @@
   }
 %% File: l3backend-draw.dtx
 \cs_new_eq:NN \__draw_backend_literal:n \__kernel_backend_literal_pdf:n
-\cs_generate_variant:Nn \__draw_backend_literal:n { e }
+\cs_new_eq:NN \__draw_backend_literal:e \__kernel_backend_literal_pdf:e
 \cs_new_protected:Npn \__draw_backend_begin:
   { \__draw_backend_scope_begin: }
 \cs_new_protected:Npn \__draw_backend_end:
@@ -480,14 +489,19 @@
   { \__draw_backend_literal:n { 1 ~ j } }
 \cs_new_protected:Npn \__draw_backend_join_bevel:
   { \__draw_backend_literal:n { 2 ~ j } }
-\cs_new_protected:Npn \__draw_backend_cm:nnnn #1#2#3#4
+\cs_new_protected:Npn \__draw_backend_transform:nnnn #1#2#3#4
   {
     \__kernel_backend_matrix:n { #1 ~ #2 ~ #3 ~ #4 }
   }
+\cs_new_protected:Npn \__draw_backend_shift:nn #1#2
+  {
+    \__draw_backend_literal:n
+      { 1 ~ 0 ~ 0 ~ 1 ~ #1 ~ #2 ~ cm }
+  }
 \cs_new_protected:Npn \__draw_backend_box_use:Nnnnn #1#2#3#4#5
   {
     \__kernel_backend_scope_begin:
-    \__draw_backend_cm:nnnn {#2} {#3} {#4} {#5}
+    \__kernel_backend_matrix:n { #2 ~ #3 ~ #4 ~ #5 }
     \hbox_overlap_right:n { \box_use:N #1 }
     \__kernel_backend_scope_end:
   }
@@ -648,46 +662,6 @@
       { \int_use:N \tex_pdflastximagepages:D }
   }
 %% File: l3backend-pdf.dtx
-\box_new:N \l__pdf_internal_box
-\cs_new_protected:Npn \__pdf_backend_annotation:nnnn #1#2#3#4
-  {
-    \tex_pdfextension:D annot ~
-      width  ~ \dim_eval:n {#1} ~
-      height ~ \dim_eval:n {#2} ~
-      depth  ~ \dim_eval:n {#3} ~
-      {#4}
-  }
-\cs_new:Npe \__pdf_backend_annotation_last:
-  {
-    \exp_not:N \int_value:w
-      \exp_not:N \tex_pdffeedback:D lastannot ~
-      \c_space_tl 0 ~ R
-  }
-\cs_new_protected:Npn \__pdf_backend_link_begin_goto:nnw #1#2
-  { \__pdf_backend_link_begin:nnnw {#1} { goto~name } {#2} }
-\cs_new_protected:Npn \__pdf_backend_link_begin_user:nnw #1#2
-  { \__pdf_backend_link_begin:nnnw {#1} { user } {#2} }
-\cs_new_protected:Npn \__pdf_backend_link_begin:nnnw #1#2#3
-  {
-    \tex_pdfextension:D startlink ~
-      attr {#1}
-      #2 {#3}
-  }
-\cs_new_protected:Npn \__pdf_backend_link_end:
-  {
-    \tex_pdfextension:D endlink \scan_stop:
-  }
-\cs_new:Npe \__pdf_backend_link_last:
-  {
-    \exp_not:N \int_value:w
-      \exp_not:N \tex_pdffeedback:D lastlink ~
-      \c_space_tl 0 ~ R
-  }
-\cs_new_protected:Npn \__pdf_backend_link_margin:n #1
-  {
-    \tex_pdfvariable:D linkmargin
-      \dim_eval:n {#1} \scan_stop:
-  }
 \cs_new_protected:Npn \__pdf_backend_destination:nn #1#2
   {
     \tex_pdfextension:D dest ~
@@ -832,6 +806,62 @@
     \dim_gset:Nn \tex_pagewidth:D  {#1}
     \dim_gset:Nn \tex_pageheight:D {#2}
   }
+%% File: l3backend-pdfannot.dtx
+\cs_new_protected:Npn \__pdfannot_backend_generic:nnnn #1#2#3#4
+  {
+    \tex_pdfextension:D annot ~
+      width  ~ \dim_eval:n {#1} ~
+      height ~ \dim_eval:n {#2} ~
+      depth  ~ \dim_eval:n {#3} ~
+      {#4}
+  }
+\cs_new:Npe \__pdfannot_backend_last:
+  {
+    \exp_not:N \int_value:w
+      \exp_not:N \tex_pdffeedback:D lastannot ~
+      \c_space_tl 0 ~ R
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_goto:nnw #1#2
+  { \__pdfannot_backend_link_begin:nnnw {#1} { goto~name } {#2} }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_user:nnw #1#2
+  { \__pdfannot_backend_link_begin:nnnw {#1} { user } {#2} }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin:nnnw #1#2#3
+  {
+    \tex_pdfextension:D startlink ~
+      attr {#1}
+      #2 {#3}
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_end:
+  {
+    \tex_pdfextension:D endlink \scan_stop:
+  }
+\cs_new:Npe \__pdfannot_backend_link_last:
+  {
+    \exp_not:N \int_value:w
+      \exp_not:N \tex_pdffeedback:D lastlink ~
+      \c_space_tl 0 ~ R
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_margin:n #1
+  {
+    \tex_pdfvariable:D linkmargin
+      \dim_eval:n {#1} \scan_stop:
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_on:
+  { \tex_pdfextension:D linkstate 0 ~ }
+\cs_new_protected:Npn \__pdfannot_backend_link_off:
+  { \tex_pdfextension:D linkstate 1 ~ }
+\cs_new_eq:NN \__pdf_backend_annotation:nnnn \__pdfannot_backend_generic:nnnn
+\cs_new_eq:NN \__pdf_backend_annotation_last: \__pdfannot_backend_last:
+\clist_map_inline:nn
+  {
+    begin_goto:nnw ,
+    begin_user:nnw ,
+    begin:nnnw     ,
+    end:           ,
+    last:          ,
+    margin:n
+  }
+  { \cs_new_eq:cc { __pdf_backend_link_ #1 } { __pdfannot_backend_link_ #1 } }
 %% File: l3backend-opacity.dtx
 \bool_lazy_and:nnT
   { \cs_if_exist_p:N \pdfmanagement_if_active_p: }

Modified: trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.lua
===================================================================
--- trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.lua	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.lua	2025-03-11 20:09:53 UTC (rev 74575)
@@ -7,7 +7,7 @@
 -- l3backend-color.dtx  (with options: `lua')
 -- l3backend-opacity.dtx  (with options: `lua')
 -- 
--- Copyright (C) 2023,2024 The LaTeX Project
+-- Copyright (C) 2023-2025 The LaTeX Project
 -- 
 -- It may be distributed and/or modified under the conditions of
 -- the LaTeX Project Public License (LPPL), either version 1.3c of

Modified: trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-pdftex.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-pdftex.def	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-pdftex.def	2025-03-11 20:09:53 UTC (rev 74575)
@@ -10,9 +10,10 @@
 %% l3backend-draw.dtx  (with options: `package,pdftex')
 %% l3backend-graphics.dtx  (with options: `package,pdftex')
 %% l3backend-pdf.dtx  (with options: `package,pdftex')
+%% l3backend-pdfannot.dtx  (with options: `package,pdftex')
 %% l3backend-opacity.dtx  (with options: `package,pdftex')
 %% 
-%% Copyright (C) 2019-2024 The LaTeX Project
+%% Copyright (C) 2019-2025 The LaTeX Project
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -26,7 +27,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-pdftex.def}{2024-05-08}{}
+  {l3backend-pdftex.def}{2025-03-10}{}
   {L3 backend support: PDF output (pdfTeX)}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -60,7 +61,11 @@
     \tex_pdfliteral:D
       { \exp_not:n {#1} }
   }
-\cs_generate_variant:Nn \__kernel_backend_literal_pdf:n { e }
+\cs_new_protected:Npn \__kernel_backend_literal_pdf:e #1
+  {
+    \tex_pdfliteral:D
+      {#1}
+  }
 \cs_new_protected:Npn \__kernel_backend_literal_page:n #1
   {
     \tex_pdfliteral:D
@@ -84,7 +89,11 @@
     \tex_pdfsetmatrix:D
         { \exp_not:n {#1} }
   }
-\cs_generate_variant:Nn \__kernel_backend_matrix:n { e }
+\cs_new_protected:Npn \__kernel_backend_matrix:e #1
+  {
+    \tex_pdfsetmatrix:D
+        {#1}
+  }
 %% File: l3backend-color.dtx
 \int_new:N \l__color_backend_stack_int
 \cs_new_protected:Npn \__kernel_color_backend_stack_init:Nnn #1#2#3
@@ -383,7 +392,7 @@
   }
 %% File: l3backend-draw.dtx
 \cs_new_eq:NN \__draw_backend_literal:n \__kernel_backend_literal_pdf:n
-\cs_generate_variant:Nn \__draw_backend_literal:n { e }
+\cs_new_eq:NN \__draw_backend_literal:e \__kernel_backend_literal_pdf:e
 \cs_new_protected:Npn \__draw_backend_begin:
   { \__draw_backend_scope_begin: }
 \cs_new_protected:Npn \__draw_backend_end:
@@ -479,14 +488,19 @@
   { \__draw_backend_literal:n { 1 ~ j } }
 \cs_new_protected:Npn \__draw_backend_join_bevel:
   { \__draw_backend_literal:n { 2 ~ j } }
-\cs_new_protected:Npn \__draw_backend_cm:nnnn #1#2#3#4
+\cs_new_protected:Npn \__draw_backend_transform:nnnn #1#2#3#4
   {
     \__kernel_backend_matrix:n { #1 ~ #2 ~ #3 ~ #4 }
   }
+\cs_new_protected:Npn \__draw_backend_shift:nn #1#2
+  {
+    \__draw_backend_literal:n
+      { 1 ~ 0 ~ 0 ~ 1 ~ #1 ~ #2 ~ cm }
+  }
 \cs_new_protected:Npn \__draw_backend_box_use:Nnnnn #1#2#3#4#5
   {
     \__kernel_backend_scope_begin:
-    \__draw_backend_cm:nnnn {#2} {#3} {#4} {#5}
+    \__kernel_backend_matrix:n { #2 ~ #3 ~ #4 ~ #5 }
     \hbox_overlap_right:n { \box_use:N #1 }
     \__kernel_backend_scope_end:
   }
@@ -647,46 +661,6 @@
       { \int_use:N \tex_pdflastximagepages:D }
   }
 %% File: l3backend-pdf.dtx
-\box_new:N \l__pdf_internal_box
-\cs_new_protected:Npn \__pdf_backend_annotation:nnnn #1#2#3#4
-  {
-    \tex_pdfannot:D
-      width  ~ \dim_eval:n {#1} ~
-      height ~ \dim_eval:n {#2} ~
-      depth  ~ \dim_eval:n {#3} ~
-      {#4}
-  }
-\cs_new:Npe \__pdf_backend_annotation_last:
-  {
-    \exp_not:N \int_value:w
-      \exp_not:N \tex_pdflastannot:D
-      \c_space_tl 0 ~ R
-  }
-\cs_new_protected:Npn \__pdf_backend_link_begin_goto:nnw #1#2
-  { \__pdf_backend_link_begin:nnnw {#1} { goto~name } {#2} }
-\cs_new_protected:Npn \__pdf_backend_link_begin_user:nnw #1#2
-  { \__pdf_backend_link_begin:nnnw {#1} { user } {#2} }
-\cs_new_protected:Npn \__pdf_backend_link_begin:nnnw #1#2#3
-  {
-    \tex_pdfstartlink:D
-      attr {#1}
-      #2 {#3}
-  }
-\cs_new_protected:Npn \__pdf_backend_link_end:
-  {
-    \tex_pdfendlink:D
-  }
-\cs_new:Npe \__pdf_backend_link_last:
-  {
-    \exp_not:N \int_value:w
-      \exp_not:N \tex_pdflastlink:D
-      \c_space_tl 0 ~ R
-  }
-\cs_new_protected:Npn \__pdf_backend_link_margin:n #1
-  {
-    \tex_pdflinkmargin:D
-      \dim_eval:n {#1} \scan_stop:
-  }
 \cs_new_protected:Npn \__pdf_backend_destination:nn #1#2
   {
     \tex_pdfdest:D
@@ -831,6 +805,62 @@
     \dim_gset:Nn \tex_pagewidth:D  {#1}
     \dim_gset:Nn \tex_pageheight:D {#2}
   }
+%% File: l3backend-pdfannot.dtx
+\cs_new_protected:Npn \__pdfannot_backend_generic:nnnn #1#2#3#4
+  {
+    \tex_pdfannot:D
+      width  ~ \dim_eval:n {#1} ~
+      height ~ \dim_eval:n {#2} ~
+      depth  ~ \dim_eval:n {#3} ~
+      {#4}
+  }
+\cs_new:Npe \__pdfannot_backend_last:
+  {
+    \exp_not:N \int_value:w
+      \exp_not:N \tex_pdflastannot:D
+      \c_space_tl 0 ~ R
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_goto:nnw #1#2
+  { \__pdfannot_backend_link_begin:nnnw {#1} { goto~name } {#2} }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_user:nnw #1#2
+  { \__pdfannot_backend_link_begin:nnnw {#1} { user } {#2} }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin:nnnw #1#2#3
+  {
+    \tex_pdfstartlink:D
+      attr {#1}
+      #2 {#3}
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_end:
+  {
+    \tex_pdfendlink:D
+  }
+\cs_new:Npe \__pdfannot_backend_link_last:
+  {
+    \exp_not:N \int_value:w
+      \exp_not:N \tex_pdflastlink:D
+      \c_space_tl 0 ~ R
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_margin:n #1
+  {
+    \tex_pdflinkmargin:D
+      \dim_eval:n {#1} \scan_stop:
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_on:
+   { \tex_pdfrunninglinkon:D }
+\cs_new_protected:Npn \__pdfannot_backend_link_off:
+  { \tex_pdfrunninglinkoff:D }
+\cs_new_eq:NN \__pdf_backend_annotation:nnnn \__pdfannot_backend_generic:nnnn
+\cs_new_eq:NN \__pdf_backend_annotation_last: \__pdfannot_backend_last:
+\clist_map_inline:nn
+  {
+    begin_goto:nnw ,
+    begin_user:nnw ,
+    begin:nnnw     ,
+    end:           ,
+    last:          ,
+    margin:n
+  }
+  { \cs_new_eq:cc { __pdf_backend_link_ #1 } { __pdfannot_backend_link_ #1 } }
 %% File: l3backend-opacity.dtx
 \bool_lazy_and:nnT
   { \cs_if_exist_p:N \pdfmanagement_if_active_p: }

Modified: trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-xetex.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-xetex.def	2025-03-11 20:09:40 UTC (rev 74574)
+++ trunk/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-xetex.def	2025-03-11 20:09:53 UTC (rev 74575)
@@ -10,9 +10,10 @@
 %% l3backend-draw.dtx  (with options: `package,xetex')
 %% l3backend-graphics.dtx  (with options: `package,xetex')
 %% l3backend-pdf.dtx  (with options: `package,xetex')
+%% l3backend-pdfannot.dtx  (with options: `package,xetex')
 %% l3backend-opacity.dtx  (with options: `package,xetex')
 %% 
-%% Copyright (C) 2019-2024 The LaTeX Project
+%% Copyright (C) 2019-2025 The LaTeX Project
 %% 
 %% It may be distributed and/or modified under the conditions of
 %% the LaTeX Project Public License (LPPL), either version 1.3c of
@@ -26,7 +27,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-xetex.def}{2024-05-08}{}
+  {l3backend-xetex.def}{2025-03-10}{}
   {L3 backend support: XeTeX}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -306,7 +307,7 @@
   }
 %% File: l3backend-draw.dtx
 \cs_new_eq:NN \__draw_backend_literal:n \__kernel_backend_literal_pdf:n
-\cs_generate_variant:Nn \__draw_backend_literal:n { e }
+\cs_new_eq:NN \__draw_backend_literal:e \__kernel_backend_literal_pdf:e
 \cs_new_protected:Npn \__draw_backend_begin:
   { \__draw_backend_scope_begin: }
 \cs_new_protected:Npn \__draw_backend_end:
@@ -402,12 +403,20 @@
   { \__draw_backend_literal:n { 1 ~ j } }
 \cs_new_protected:Npn \__draw_backend_join_bevel:
   { \__draw_backend_literal:n { 2 ~ j } }
-\cs_new_protected:Npn \__draw_backend_cm:nnnn #1#2#3#4
+\cs_new_protected:Npn \__draw_backend_transform:nnnn #1#2#3#4
   {
-    \__draw_backend_cm_decompose:nnnnN {#1} {#2} {#3} {#4}
-      \__draw_backend_cm_aux:nnnn
+    \str_if_eq:nnTF { #2 ~ #3 } { 0 ~ 0 }
+      {
+        \__kernel_backend_literal:n { x:rotate~0 }
+        \__kernel_backend_literal:n { x:scale~#1~#4 }
+        \__kernel_backend_literal:n { x:rotate~0 }
+      }
+      {
+        \__draw_backend_transform_decompose:nnnnN {#1} {#2} {#3} {#4}
+          \__draw_backend_transform_aux:nnnn
+      }
   }
-\cs_new_protected:Npn \__draw_backend_cm_aux:nnnn #1#2#3#4
+\cs_new_protected:Npn \__draw_backend_transform_aux:nnnn #1#2#3#4
   {
     \__kernel_backend_literal:e
       {
@@ -430,11 +439,16 @@
           { \fp_eval:n { round ( -#4 , 5 ) } }
       }
   }
-\cs_new_protected:Npn \__draw_backend_cm_decompose:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \__draw_backend_shift:nn #1#2
   {
+    \__draw_backend_literal:n
+      { 1 ~ 0 ~ 0 ~ 1 ~ #1 ~ #2 ~ cm }
+  }
+\cs_new_protected:Npn \__draw_backend_transform_decompose:nnnnN #1#2#3#4#5
+  {
     \use:e
       {
-        \__draw_backend_cm_decompose_auxi:nnnnN
+        \__draw_backend_transform_decompose_auxi:nnnnN
           { \fp_eval:n { (#1 + #4) / 2 } }
           { \fp_eval:n { (#1 - #4) / 2 } }
           { \fp_eval:n { (#3 + #2) / 2 } }
@@ -442,11 +456,11 @@
       }
         #5
   }
-\cs_new_protected:Npn \__draw_backend_cm_decompose_auxi:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \__draw_backend_transform_decompose_auxi:nnnnN #1#2#3#4#5
   {
     \use:e
       {
-        \__draw_backend_cm_decompose_auxii:nnnnN
+        \__draw_backend_transform_decompose_auxii:nnnnN
           { \fp_eval:n { 2 * sqrt ( #1 * #1 + #4 * #4 ) } }
           { \fp_eval:n { 2 * sqrt ( #2 * #2 + #3 * #3 ) } }
           { \fp_eval:n { atand ( #3 , #2 ) } }
@@ -454,11 +468,11 @@
       }
         #5
   }
-\cs_new_protected:Npn \__draw_backend_cm_decompose_auxii:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \__draw_backend_transform_decompose_auxii:nnnnN #1#2#3#4#5
   {
     \use:e
       {
-        \__draw_backend_cm_decompose_auxiii:nnnnN
+        \__draw_backend_transform_decompose_auxiii:nnnnN
           { \fp_eval:n { ( #4 - #3 ) / 2 } }
           { \fp_eval:n { ( #1 + #2 ) / 2 } }
           { \fp_eval:n { ( #1 - #2 ) / 2 } }
@@ -466,7 +480,7 @@
       }
         #5
   }
-\cs_new_protected:Npn \__draw_backend_cm_decompose_auxiii:nnnnN #1#2#3#4#5
+\cs_new_protected:Npn \__draw_backend_transform_decompose_auxiii:nnnnN #1#2#3#4#5
   {
     \fp_compare:nNnTF { abs( #2 ) } > { abs ( #3 ) }
       { #5 {#1} {#2} {#3} {#4} }
@@ -653,7 +667,6 @@
       }
   }
 %% File: l3backend-pdf.dtx
-\box_new:N \l__pdf_internal_box
 \cs_new_protected:Npe \__pdf_backend:n #1
   { \__kernel_backend_literal:n { pdf: #1 } }
 \cs_generate_variant:Nn \__pdf_backend:n { e }
@@ -706,48 +719,6 @@
   { @pdf.obj \int_use:N \g__pdf_backend_object_int }
 \cs_new:Npn \__pdf_backend_pageobject_ref:n #1
   { @page #1 }
-\int_new:N \g__pdf_backend_annotation_int
-\cs_new_protected:Npn \__pdf_backend_annotation:nnnn #1#2#3#4
-  {
-    \int_gincr:N \g__pdf_backend_object_int
-    \int_gset_eq:NN \g__pdf_backend_annotation_int \g__pdf_backend_object_int
-    \__pdf_backend:e
-      {
-        ann ~ @pdf.obj \int_use:N \g__pdf_backend_object_int \c_space_tl
-        width  ~ \dim_eval:n {#1} ~
-        height ~ \dim_eval:n {#2} ~
-        depth  ~ \dim_eval:n {#3} ~
-        << /Type /Annot #4 >>
-      }
-  }
-\cs_new:Npn \__pdf_backend_annotation_last:
-  { @pdf.obj \int_use:N \g__pdf_backend_annotation_int }
-\int_new:N \g__pdf_backend_link_int
-\cs_new_protected:Npn \__pdf_backend_link_begin_goto:nnw #1#2
-  { \__pdf_backend_link_begin:n { #1 /Subtype /Link /A << /S /GoTo /D ( #2 ) >> } }
-\cs_new_protected:Npn \__pdf_backend_link_begin_user:nnw #1#2
-  { \__pdf_backend_link_begin:n {#1#2} }
-\cs_new_protected:Npe \__pdf_backend_link_begin:n #1
-  {
-    \exp_not:N \int_gincr:N \exp_not:N  \g__pdf_backend_link_int
-    \__pdf_backend:e
-      {
-        bann ~
-        @pdf.lnk
-        \exp_not:N \int_use:N \exp_not:N  \g__pdf_backend_link_int
-        \c_space_tl
-        <<
-          /Type /Annot
-          #1
-        >>
-      }
-  }
-\cs_new_protected:Npn \__pdf_backend_link_end:
-  { \__pdf_backend:n { eann } }
-\cs_new:Npn \__pdf_backend_link_last:
-  { @pdf.lnk \int_use:N \g__pdf_backend_link_int }
-\cs_new_protected:Npn \__pdf_backend_link_margin:n #1
-  { \__kernel_backend_literal:e { dvipdfmx:config~g~ \dim_eval:n {#1} } }
 \cs_new_protected:Npn \__pdf_backend_destination:nn #1#2
   {
     \__pdf_backend:e
@@ -836,6 +807,70 @@
     \dim_gset:Nn \tex_pagewidth:D  {#1}
     \dim_gset:Nn \tex_pageheight:D {#2}
   }
+%% File: l3backend-pdfannot.dtx
+\cs_new_protected:Npe \__pdfannot_backend:n #1
+  { \__kernel_backend_literal:n { pdf: #1 } }
+\cs_generate_variant:Nn \__pdfannot_backend:n { e }
+\int_new:N \g__pdfannot_backend_int
+\cs_new_protected:Npn \__pdfannot_backend_generic:nnnn #1#2#3#4
+  {
+    \int_gincr:N \g__pdfannot_backend_int
+    \__pdfannot_backend:e
+      {
+        ann ~ @pdfannot \int_use:N \g__pdfannot_backend_int \c_space_tl
+        width  ~ \dim_eval:n {#1} ~
+        height ~ \dim_eval:n {#2} ~
+        depth  ~ \dim_eval:n {#3} ~
+        << /Type /Annot #4 >>
+      }
+  }
+\cs_new:Npn \__pdfannot_backend_last:
+  { @pdfannot \int_use:N \g__pdfannot_backend_int }
+\int_new:N \g__pdfannot_backend_link_int
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_goto:nnw #1#2
+  {
+    \__pdfannot_backend_link_begin:n
+      { #1 /Subtype /Link /A << /S /GoTo /D ( #2 ) >> }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_begin_user:nnw #1#2
+  { \__pdfannot_backend_link_begin:n {#1#2} }
+\cs_new_protected:Npe \__pdfannot_backend_link_begin:n #1
+  {
+    \int_gincr:N \exp_not:N \g__pdfannot_backend_int
+    \int_gset_eq:NN \exp_not:N \g__pdfannot_backend_link_int
+      \exp_not:N \g__pdfannot_backend_int
+    \__pdfannot_backend:e
+      {
+        bann ~
+        @pdfannot
+        \exp_not:N \int_use:N \exp_not:N \g__pdfannot_backend_link_int
+        \c_space_tl
+        <<
+          /Type /Annot
+          #1
+        >>
+      }
+  }
+\cs_new_protected:Npn \__pdfannot_backend_link_end:
+  { \__pdfannot_backend:n { eann } }
+\cs_new:Npn \__pdfannot_backend_link_last:
+  { @pdfannot \int_use:N \g__pdfannot_backend_link_int }
+\cs_new_protected:Npn \__pdfannot_backend_link_margin:n #1
+  { \__kernel_backend_literal:e { dvipdfmx:config~g~ \dim_eval:n {#1} } }
+\cs_new_protected:Npn \__pdfannot_backend_link_on:  { \__pdfannot_backend:n { link } }
+\cs_new_protected:Npn \__pdfannot_backend_link_off: { \__pdfannot_backend:n { nolink } }
+\cs_new_eq:NN \__pdf_backend_annotation:nnnn \__pdfannot_backend_generic:nnnn
+\cs_new_eq:NN \__pdf_backend_annotation_last: \__pdfannot_backend_last:
+\clist_map_inline:nn
+  {
+    begin_goto:nnw ,
+    begin_user:nnw ,
+    begin:nnnw     ,
+    end:           ,
+    last:          ,
+    margin:n
+  }
+  { \cs_new_eq:cc { __pdf_backend_link_ #1 } { __pdfannot_backend_link_ #1 } }
 %% File: l3backend-opacity.dtx
 \bool_lazy_and:nnT
   { \cs_if_exist_p:N \pdfmanagement_if_active_p: }



More information about the tex-live-commits mailing list.