% \iffalse meta-comment
%
%% File: l3backend-basics.dtx
%
% Copyright (C) 2019-2026 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-basics} module\\ Backend basics^^A
% }
%
% \author{^^A
%  The \LaTeX{} Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released 2026-02-18}
%
% \maketitle
%
% \begin{documentation}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3backend-basics} implementation}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
% Whilst there is a reasonable amount of code overlap between backends,
% it is much clearer to have the blocks more-or-less separated than run
% in together and DocStripped out in parts. As such, most of the following
% is set up on a per-backend basis, though there is some common code (again
% given in blocks not interspersed with other material).
%
% All the file identifiers are up-front so that they come out in the right
% place in the files.
%    \begin{macrocode}
\ProvidesExplFile
%<*dvipdfmx>
  {l3backend-dvipdfmx.def}{2026-02-18}{}
  {L3 backend support: dvipdfmx}
%</dvipdfmx>
%<*dvips>
  {l3backend-dvips.def}{2026-02-18}{}
  {L3 backend support: dvips}
%</dvips>
%<*dvisvgm>
  {l3backend-dvisvgm.def}{2026-02-18}{}
  {L3 backend support: dvisvgm}
%</dvisvgm>
%<*luatex>
  {l3backend-luatex.def}{2026-02-18}{}
  {L3 backend support: PDF output (LuaTeX)}
%</luatex>
%<*pdftex>
  {l3backend-pdftex.def}{2026-02-18}{}
  {L3 backend support: PDF output (pdfTeX)}
%</pdftex>
%<*xetex>
  {l3backend-xetex.def}{2026-02-18}{}
  {L3 backend support: XeTeX}
%</xetex>
%    \end{macrocode}
%
%   Check if the loaded kernel is at least enough to load this file.
%   The kernel date has to be at least equal to \cs{ExplBackendFileDate}
%   or later.  If \cs{__kernel_dependency_version_check:Nn} doesn't
%   exist we're loading in an older kernel, so it's an error anyway.
%   With time, this test should vanish and only the dependency check
%   should remain.
%    \begin{macrocode}
\cs_if_exist:NTF \__kernel_dependency_version_check:nn
  {
    \__kernel_dependency_version_check:nn {2023-10-10}
%<dvipdfmx>      {l3backend-dvipdfmx.def}
%<dvips>      {l3backend-dvips.def}
%<dvisvgm>      {l3backend-dvisvgm.def}
%<luatex>      {l3backend-luatex.def}
%<pdftex>      {l3backend-pdftex.def}
%<xetex>      {l3backend-xetex.def}
  }
  {
    \cs_if_exist_use:cF { @latex@error } { \errmessage }
      {
        Mismatched~LaTeX~support~files~detected. \MessageBreak
        Loading~aborted!
      }
      { \use:c { @ehd } }
    \tex_endinput:D
  }
%    \end{macrocode}
%
% The order of the backend code here is such that we get somewhat logical
% outcomes in terms of code sharing whilst keeping things readable. (Trying to
% mix all of the code by concept is almost unmanageable.) The key parts which
% are shared are
% \begin{itemize}
%   \item Color support is either \texttt{dvips}-like or \LuaTeX{}/pdfTeX{}-like.
%   \item \LuaTeX{}/pdfTeX{} and \texttt{dvipdfmx}/\XeTeX{} share drawing routines.
%   \item \XeTeX{} is the same as \texttt{dvipdfmx} other than image size
%     extraction so takes most of the same code.
% \end{itemize}
%
% \begin{macro}
%   {
%     \__kernel_backend_literal:e,
%     \__kernel_backend_literal:n
%   }
%  The one shared function for all backends is access to the basic
%  \tn{special} primitive: it has slightly odd expansion behavior
%  so a wrapper is provided.
%    \begin{macrocode}
\cs_new_eq:NN \__kernel_backend_literal:e \tex_special:D
\cs_new_protected:Npn \__kernel_backend_literal:n #1
  { \__kernel_backend_literal:e { \exp_not:n {#1} } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__kernel_backend_first_shipout:n}
%   We need to write at first shipout in a few places. As we want to use the
%   most up-to-date method, 
%    \begin{macrocode}
\cs_if_exist:NTF \@ifl@t@r
  {
    \@ifl@t@r \fmtversion { 2020-10-01 }
      {
        \cs_new_protected:Npn \__kernel_backend_first_shipout:n #1
          { \hook_gput_code:nnn { shipout / firstpage } { l3backend } {#1} }
      }
      { \cs_new_eq:NN \__kernel_backend_first_shipout:n \AtBeginDvi }
  }
  { \cs_new_eq:NN \__kernel_backend_first_shipout:n \use:n }
%    \end{macrocode}
% \end{macro}
%
% \subsection{\texttt{dvips} backend}
%
%    \begin{macrocode}
%<*dvips>
%    \end{macrocode}
%
% \begin{macro}
%   {\__kernel_backend_literal_postscript:n, \__kernel_backend_literal_postscript:e}
%   Literal PostScript can be included using a few low-level formats. Here,
%   we use the form with no positioning: this is overall more convenient as
%   a wrapper. Note that this does require that where position is important,
%   an appropriate wrapper is included.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_literal_postscript:n #1
  { \__kernel_backend_literal:n { ps:: #1 } }
\cs_generate_variant:Nn \__kernel_backend_literal_postscript:n { e }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__kernel_backend_postscript:n, \__kernel_backend_postscript:e}
%   PostScript data that does have positioning, and also applying
%   a shift to |SDict| (which is not done automatically by
%   |ps:| or |ps::|, in contrast to |!| or |"|).
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_postscript:n #1
  { \__kernel_backend_literal:n { ps: SDict ~ begin ~ #1 ~ end } }
\cs_generate_variant:Nn \__kernel_backend_postscript:n { e }
%    \end{macrocode}
% \end{macro}
%
% PostScript for the header: a small saving but makes the code clearer.
% This is held until the start of shipout such that a document with no
% actual output does not write anything.
%    \begin{macrocode}
\bool_if:NT \g__kernel_backend_header_bool
  {
    \__kernel_backend_first_shipout:n
      { \__kernel_backend_literal:n { header = l3backend-dvips.pro } }
  }
%    \end{macrocode}
%
% \begin{macro}
%   {
%     \__kernel_backend_align_begin:,
%     \__kernel_backend_align_end:
%   }
%   In \texttt{dvips} there is no built-in saving of the current
%   position, and so some additional PostScript is required to set up the
%   transformation matrix and also to restore it afterwards. Notice the use
%   of the stack to save the current position \enquote{up front} and to
%   move back to it at the end of the process. Notice that the |[begin]|/^^A
%   |[end]| pair here mean that we can use a run of PostScript statements
%   in separate lines: not \emph{required} but does make the code and
%   output more clear.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_align_begin:
  {
    \__kernel_backend_literal:n { ps::[begin] }
    \__kernel_backend_literal_postscript:n { currentpoint }
    \__kernel_backend_literal_postscript:n { currentpoint~translate }
  }
\cs_new_protected:Npn \__kernel_backend_align_end:
  {
    \__kernel_backend_literal_postscript:n { neg~exch~neg~exch~translate }
    \__kernel_backend_literal:n { ps::[end] }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__kernel_backend_scope_begin:, \__kernel_backend_scope_end:}
%   Saving/restoring scope for general operations needs to be done with
%   \texttt{dvips} positioning (try without to see this!). Thus we need the
%   |ps:| version of the special here. As only the graphics state is ever
%   altered within this pairing, we use the lower-cost |g|-versions.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_scope_begin:
  { \__kernel_backend_literal:n { ps:gsave } }
\cs_new_protected:Npn \__kernel_backend_scope_end:
  { \__kernel_backend_literal:n { ps:grestore } }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</dvips>
%    \end{macrocode}
%
% \subsection{\LuaTeX{} and \pdfTeX{} backends}
%
%    \begin{macrocode}
%<*luatex|pdftex>
%    \end{macrocode}
%
% Both \LuaTeX{} and \pdfTeX{} write PDFs directly rather than via an
% intermediate file. Although there are similarities, the move of \LuaTeX{}
% to have more code in Lua means we create two independent files using
% shared DocStrip code.
%
% \begin{macro}{\__kernel_backend_literal_pdf:n, \__kernel_backend_literal_pdf:e}
%   This is equivalent to \verb|\special{pdf:}| but the engine can
%   track it. Without the \texttt{direct} keyword everything is kept in
%   sync: the transformation matrix is set to the current point automatically.
%   Note that this is still inside the text (\texttt{BT} \dots \texttt{ET}
%   block).
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_literal_pdf:n #1
  {
%<*luatex>
    \tex_pdfextension:D literal
%</luatex>
%<*pdftex>
    \tex_pdfliteral:D
%</pdftex>
      { \exp_not:n {#1} }
  }
\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}
%
% \begin{macro}{\__kernel_backend_literal_page:n, \__kernel_backend_literal_page:e}
%  Page literals are pretty simple. To avoid an expansion, we write out
%  by hand.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_literal_page:n #1
  {
%<*luatex>
    \tex_pdfextension:D literal ~
%</luatex>
%<*pdftex>
    \tex_pdfliteral:D
%</pdftex>
        page { \exp_not:n {#1} }
  }
\cs_new_protected:Npn \__kernel_backend_literal_page:e #1
  {
%<*luatex>
    \tex_pdfextension:D literal ~
%</luatex>
%<*pdftex>
    \tex_pdfliteral:D
%</pdftex>
        page {#1}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__kernel_backend_scope_begin:, \__kernel_backend_scope_end:}
%  Higher-level interfaces for saving and restoring the graphic state.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_scope_begin:
  {
%<*luatex>
    \tex_pdfextension:D save \scan_stop:
%</luatex>
%<*pdftex>
    \tex_pdfsave:D
%</pdftex>
  }
\cs_new_protected:Npn \__kernel_backend_scope_end:
  {
%<*luatex>
    \tex_pdfextension:D restore \scan_stop:
%</luatex>
%<*pdftex>
    \tex_pdfrestore:D
%</pdftex>
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__kernel_backend_matrix:n, \__kernel_backend_matrix:e}
%   Here the appropriate function is set up to insert an affine matrix
%   into the PDF. With \pdfTeX{} and \LuaTeX{} in direct PDF output mode there
%   is a primitive for this, which only needs the rotation/scaling/skew part.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_matrix:n #1
  {
%<*luatex>
    \tex_pdfextension:D setmatrix
%</luatex>
%<*pdftex>
    \tex_pdfsetmatrix:D
%</pdftex>
        { \exp_not:n {#1} }
  }
\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}
%
%    \begin{macrocode}
%</luatex|pdftex>
%    \end{macrocode}
%
% \subsection{\texttt{dvipdfmx} backend}
%
%    \begin{macrocode}
%<*dvipdfmx|xetex>
%    \end{macrocode}
%
% The \texttt{dvipdfmx} shares code with the PDF mode one (using the common
% section to this file) but also with \XeTeX{}. The latter is close
% to identical to \texttt{dvipdfmx} and so all of the code here is extracted
% for both backends, with some \texttt{clean up} for \XeTeX{} as
% required.
%
% \begin{macro}{\__kernel_backend_literal_pdf:n, \__kernel_backend_literal_pdf:e}
%   Undocumented but equivalent to \pdfTeX{}'s |literal| keyword. It's similar to
%   be not the same as the documented |contents| keyword as that adds a |q|/|Q|
%   pair.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_literal_pdf:n #1
  { \__kernel_backend_literal:n { pdf:literal~ #1 } }
\cs_generate_variant:Nn \__kernel_backend_literal_pdf:n { e }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__kernel_backend_literal_page:n}
%  Whilst the manual says this is like |literal direct| in \pdfTeX{},
%  it closes the |BT| block!
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_literal_page:n #1
  { \__kernel_backend_literal:n { pdf:literal~direct~ #1 } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__kernel_backend_scope_begin:, \__kernel_backend_scope_end:}
%   Scoping is done using the backend-specific specials. We use the versions
%   originally from \texttt{xdvidfpmx} (\texttt{x:}) as these are well-tested
%   \enquote{in the wild}.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_scope_begin:
  { \__kernel_backend_literal:n { x:gsave } }
\cs_new_protected:Npn \__kernel_backend_scope_end:
  { \__kernel_backend_literal:n { x:grestore } }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</dvipdfmx|xetex>
%    \end{macrocode}
%
% \subsection{\texttt{dvisvgm} backend}
%
%    \begin{macrocode}
%<*dvisvgm>
%    \end{macrocode}
%
% \begin{macro}{\__kernel_backend_literal_svg:n, \__kernel_backend_literal_svg:e}
%   Unlike the other backends, the requirements for making SVG files mean
%   that we can't conveniently transform all operations to the current point.
%   That makes life a bit more tricky later as that needs to be accounted for.
%   A new line is added after each call to help to keep the output readable
%   for debugging.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_literal_svg:n #1
  { \__kernel_backend_literal:n { dvisvgm:raw~ #1 { ?nl } } }
\cs_generate_variant:Nn \__kernel_backend_literal_svg:n { e }
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}{\g__kernel_backend_scope_int, \l__kernel_backend_scope_int}
%   In SVG, we need to track scope nesting as properties attach to scopes; that
%   requires a pair of \texttt{int} registers.
%    \begin{macrocode}
\int_new:N \g__kernel_backend_scope_int
\int_new:N \l__kernel_backend_scope_int
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\__kernel_backend_scope_begin:, \__kernel_backend_scope_end:}
% \begin{macro}{\__kernel_backend_scope_begin:n, \__kernel_backend_scope_begin:e}
% \begin{macro}{\__kernel_backend_scope:n, \__kernel_backend_scope:e}
%   In SVG, the need to attach concepts to a scope means we need to be sure we
%   will close all of the open scopes. That is easiest done if we only need
%   an outer \enquote{wrapper} \texttt{begin}/\texttt{end} pair, and within
%   that we apply operations as a simple scoped statements. To keep down the
%   non-productive groups, we also have a \texttt{begin} version that does take
%   an argument.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_backend_scope_begin:
  {
    \__kernel_backend_literal_svg:n { <g> }
    \int_set_eq:NN
      \l__kernel_backend_scope_int
      \g__kernel_backend_scope_int
    \group_begin:
      \int_gset:Nn \g__kernel_backend_scope_int { 1 }
  }
\cs_new_protected:Npn \__kernel_backend_scope_end:
  {
      \prg_replicate:nn
        { \g__kernel_backend_scope_int }
        { \__kernel_backend_literal_svg:n { </g> } }
    \group_end:
    \int_gset_eq:NN
      \g__kernel_backend_scope_int
      \l__kernel_backend_scope_int
  }
\cs_new_protected:Npn \__kernel_backend_scope_begin:n #1
  {
    \__kernel_backend_literal_svg:n { <g ~ #1 > }
    \int_set_eq:NN
      \l__kernel_backend_scope_int
      \g__kernel_backend_scope_int
    \group_begin:
      \int_gset:Nn \g__kernel_backend_scope_int { 1 }
  }
\cs_generate_variant:Nn \__kernel_backend_scope_begin:n { e }
\cs_new_protected:Npn \__kernel_backend_scope:n #1
  {
    \__kernel_backend_literal_svg:n { <g ~ #1 > }
    \int_gincr:N \g__kernel_backend_scope_int
  }
\cs_generate_variant:Nn \__kernel_backend_scope:n { e }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
%</dvisvgm>
%    \end{macrocode}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
