From c39651dc8234f1a4e12d273b3b75e73e29e824a3 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 18 Apr 2024 19:48:52 +0000 Subject: l3backend-dev git-svn-id: svn://tug.org/texlive/trunk@70977 c570f23f-e606-0410-a88d-b1316a301751 --- .../doc/latex-dev/l3backend/CHANGELOG.md | 402 +++++ .../texmf-dist/doc/latex-dev/l3backend/README.md | 16 + .../doc/latex-dev/l3backend/l3backend-code.pdf | Bin 0 -> 907792 bytes .../doc/latex-dev/l3backend/l3backend-code.tex | 63 + .../latex-dev/l3backend/l3backend-basics.dtx | 497 ++++++ .../source/latex-dev/l3backend/l3backend-box.dtx | 470 ++++++ .../source/latex-dev/l3backend/l3backend-color.dtx | 1356 +++++++++++++++ .../source/latex-dev/l3backend/l3backend-draw.dtx | 1067 ++++++++++++ .../latex-dev/l3backend/l3backend-graphics.dtx | 931 +++++++++++ .../latex-dev/l3backend/l3backend-header.dtx | 590 +++++++ .../latex-dev/l3backend/l3backend-opacity.dtx | 353 ++++ .../source/latex-dev/l3backend/l3backend-pdf.dtx | 1755 ++++++++++++++++++++ .../source/latex-dev/l3backend/l3backend.ins | 168 ++ .../tex/latex-dev/l3backend/l3backend-dvipdfmx.def | 859 ++++++++++ .../tex/latex-dev/l3backend/l3backend-dvips.def | 1064 ++++++++++++ .../tex/latex-dev/l3backend/l3backend-dvips.pro | 405 +++++ .../tex/latex-dev/l3backend/l3backend-dvisvgm.def | 672 ++++++++ .../tex/latex-dev/l3backend/l3backend-luatex.def | 903 ++++++++++ .../tex/latex-dev/l3backend/l3backend-luatex.lua | 125 ++ .../tex/latex-dev/l3backend/l3backend-pdftex.def | 902 ++++++++++ .../tex/latex-dev/l3backend/l3backend-xetex.def | 906 ++++++++++ Master/tlpkg/tlpsrc/l3backend-dev.tlpsrc | 3 + 22 files changed, 13507 insertions(+) create mode 100644 Master/texmf-dist/doc/latex-dev/l3backend/CHANGELOG.md create mode 100644 Master/texmf-dist/doc/latex-dev/l3backend/README.md create mode 100644 Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.pdf create mode 100644 Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.tex create mode 100644 Master/texmf-dist/source/latex-dev/l3backend/l3backend-basics.dtx create mode 100644 Master/texmf-dist/source/latex-dev/l3backend/l3backend-box.dtx create mode 100644 Master/texmf-dist/source/latex-dev/l3backend/l3backend-color.dtx create mode 100644 Master/texmf-dist/source/latex-dev/l3backend/l3backend-draw.dtx create mode 100644 Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx create mode 100644 Master/texmf-dist/source/latex-dev/l3backend/l3backend-header.dtx create mode 100644 Master/texmf-dist/source/latex-dev/l3backend/l3backend-opacity.dtx create mode 100644 Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdf.dtx create mode 100644 Master/texmf-dist/source/latex-dev/l3backend/l3backend.ins create mode 100644 Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvipdfmx.def create mode 100644 Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.def create mode 100644 Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.pro create mode 100644 Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvisvgm.def create mode 100644 Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.def create mode 100644 Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.lua create mode 100644 Master/texmf-dist/tex/latex-dev/l3backend/l3backend-pdftex.def create mode 100644 Master/texmf-dist/tex/latex-dev/l3backend/l3backend-xetex.def create mode 100644 Master/tlpkg/tlpsrc/l3backend-dev.tlpsrc (limited to 'Master') diff --git a/Master/texmf-dist/doc/latex-dev/l3backend/CHANGELOG.md b/Master/texmf-dist/doc/latex-dev/l3backend/CHANGELOG.md new file mode 100644 index 00000000000..ecd85938815 --- /dev/null +++ b/Master/texmf-dist/doc/latex-dev/l3backend/CHANGELOG.md @@ -0,0 +1,402 @@ +# Changelog +All notable changes to the `l3backend` bundle will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +this project uses date-based 'snapshot' version identifiers. + +## [Unreleased] + +## [2024-04-11] + +### Added +- Support for 'raw' PDF object IDs + +### Changed +- Update PDF object management code + +## [2024-03-14] + +### Removed +- Range guard for opacity + +### Fixed +- Initiation of opacity data (see \#1472) +- ExtGState setup for stroking opacity (issue \#1472) +- Inconsistent behavior of opacity functions w/o `pdfmanagement` + (issue \#1473) +- Redundant braces in opacity backend for dvisvgm +- Interaction of scope with box insertion with `dvips` (see \#1504) + +## [2024-02-20] + +### Fixed +- Naming of a variable in the `draw` code + +## [2024-01-04] + +### Changed +- Documentation tweaks + +## [2023-11-09] + +### Changed +- Changed `luaotfload` integration to allow coexistance with (x)color. + +## [2023-11-04] + +### Fixed +- Interaction with `luaotfload` transparency colorstacks + +## [2023-10-23] + +### Changed +- Update minimal `expl3` version required + +## [2023-10-10] + +### Changed +- Track `expl3` changes + +## [2023-04-19] + +### Changed +- Pass additional attributes when loading graphics in PDF mode + +### Fixed +- Remove a stray `>` from graphics inclusion code for `dvipdfmx` + +## [2023-03-30] + +### Changed +- Integrate `l3color` and `l3opacity` with `luaotfload` to ensure that + opacity specifications don't conflict + +## [2023-01-16] + +### Changed +- Adjust internal scope of a PDF function + +## [2022-10-26] + +### Changed +- Avoid setting media box if `\mag` is non-standard + +## [2022-09-28] + +### Changed +- Add support for media box setting + +## [2022-08-30] + +### Added +- Support for new approach to writing PDF objects + +## [2022-08-23] + +### Changed +- Approach to setting current color data from LaTeX2e + +## [2022-08-05] + +### Changed +- Add no-op backend functions for annotations with `dvisvgm` + +## [2022-07-01] + +#### Fixed +- Do not include PDF file to count pages on pdfTeX +- Opacity creation with `dvipdfmx`/XeTeX (issue [\#1106](https://github.com/latex3/latex3/issues/1106)) +- Reset opacity when no stack is available at the backend (issue [\#1107](https://github.com/latex3/latex3/issues/1107)) + +## [2022-04-20] + +### Changed +- Adjust `(x)dvipdfmx` backend approach to color following issues with + multiple color stacks in `xetex.def` +- Move some functions to `l3color` + +## [2022-04-14] + +### Added +- Support for SVG graphic inclusion by `dvisvgm` + +### Fixed +- `\color_ensure_current:` backend with DVI-based routes (issue [\#1085](https://github.com/latex3/latex3/issues/1085)) + +## [2022-04-10] + +### Added +- Support for graphics (PDF) page count extraction + +### Fixed +- Setup for graphics extension searching +- Various internal issues in graphics inclusion +- Some missing functions for `dvisvgm` color support added + +### Removed +- Support for pre-2020-11-11 `dvipdfmx` + +## [2022-02-07] + +### Fixed +- Use of color stack int in scope end for `(x)dvipdfmx` + +## [2022-01-12] + +### Changed +- Move some functions to `l3color` + +## [2021-12-14] + +### Fixed +- Scoping issues for `dvisvgm` +- Some incorrect functions in `l3draw` backend for `dvisvgm` + +## [2021-10-17] + +### Changed +- Better DeviceN support + +## [2021-10-12] + +### Fixed +- Issues with creating DeviceN color spaces + +## [2021-08-04] + +### Changed +- Only use `pdfmanagement` module if active + +## [2021-07-12] + +### Fixed +- GoTo link formation for Distiller-based workflows (issue [\#957](https://github.com/latex3/latex3/issues/957)) +- Support transparency with Distiller + +## [2021-05-07] + +### Changed +- `\pdf_version_gset:n` in `dvips` now sets `\pdf_version_minor:` and + `\pdf_version_major:`. This doesn't set the PDF version but allows to test + which version the user intents to create. + +## [2021-03-18] + +### Fixed +- Maintain stack color correctly with `(x)dvipdfmx` + +## [2021-03-02] + +### Changed +- Drop 'correction' for link placement in `(x)dvidpfmx`: no longer required +- Define `\main@pdfcolorstack` for `(x)dvipdfmx` if it does not exist + +### Fixed +- Initialisation of color stacks for `(x)dvipdfmx` + +## [2021-02-18] + +### Changed +- Update tracking of PDF management functions + +### Fixed +- Opacity support for pdfTeX/LuaTeX + +## [2021-02-06] + +### Changed +- Use new (internal) interface for kerns + +## [2021-01-29] + +### Added +- Basic opacity support + +### Changed +- Use color stack for fill color, and for stroke color if possible + +### Fixed +- Implementation of `filldraw` for `dvips` + +## [2021-01-09] + +### Added +- Support for referencing last link with `(x)dvipdfmx` (requires an up-to-date + backend) + +### Changed +- Implementation of color wtih (x)dvipdfmx (requires an up-to-date + backend) + +## [2020-09-24] + +### Fixed +- Documented source as PDF + +## [2020-09-11] + +### Added +- Support for CIELAB separations with `dvips` + +### Fixed +- Some PDF object functions +- Separation color selection for `dvipdfmx`/XeTeX +- Logic for some aspects of CIELAB Separation color + +## [2020-09-01] + +### Changed +- Improved support for Separation colors +- Updated approach to `dvipdfmx`/XeTeX color support +- Split `pdfmode` driver into pdfTeX- and LuaTeX-specific files +- Renamed `xdvipdfmx` backend files to `xetex` + +## [2020-08-07] + +### Changed +- Color selection implementation +- Improved support for Separation colors + +## [2020-06-29] + +### Fixed +- Loading with `dvisvgm` + +## [2020-06-23] + +### Changed +- Improved color support for drawings with `dvisvgm` + +### Fixed +- Loading with `dvisvgm` + +## [2020-06-18] + +### Changed +- Use `scn` operator for separations +- Internal color model +- Internal performance enhancements + +## [2020-06-03] + +### Fixed +- Unneeded `[nobreak]` in `dvips` driver (issue [\#709](https://github.com/latex3/latex3/issues/709)) +- `\__pdf_backend_object_write_fstream:nn` with `dvips` backend (issue [\#710](https://github.com/latex3/latex3/issues/710)) +- Array writing in `dvips` mode + +## [2020-05-05] + +### Added +- `\__pdf_backend_pageobject_ref:n` + +### Changed +- Extend PDF compression control to `dvips` + +## [2020-03-12] + +### Fixed +- Creation of PDF annotations with `dvips` backend + +## [2020-02-23] + +### Fixed +- Mismatch between release tag and CTAN version + +## [2020-02-21] + +### Added +- Support for suppressing backend headers (see matching change in + `l3kernel`) + +## [2020-02-03] + +### Fixed +- Corrected release string information + +## [2019-11-25] + +### Changed +- Move dvips header material to `.pro` file + +## [2019-10-11] + +### Changed +- Improved functionality in generic mode + +## [2019-09-05] + +### Added +- Support for EPS and PDF files with `dvisvgm` backend + +### Fixed +- Some primitive use in the `dvips` backend + +## [2019-08-25] + +### Fixed +- Setting for PDF version in `dvipdfmx` route +- Support for PDF objects with XeTeX + +## [2019-07-01] + +### Added +- Driver support for anonymous objects + +### Changed +- Moved backend code to separate release module `l3backend` +- Include `l3backend` in file names +- Moved backend code to internal for each 'parent' module + +[Unreleased]: https://github.com/latex3/latex3/compare/2024-04-11...HEAD +[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 +[2024-02-20]: https://github.com/latex3/latex3/compare/2024-01-04...2024-02-20 +[2024-01-04]: https://github.com/latex3/latex3/compare/2023-11-09...2024-01-04 +[2023-11-09]: https://github.com/latex3/latex3/compare/2023-11-04...2023-11-09 +[2023-11-04]: https://github.com/latex3/latex3/compare/2023-10-23...2023-11-04 +[2023-10-23]: https://github.com/latex3/latex3/compare/2023-10-10...2023-10-23 +[2023-10-10]: https://github.com/latex3/latex3/compare/2023-04-19...2023-10-10 +[2023-04-19]: https://github.com/latex3/latex3/compare/2023-03-30...2023-04-19 +[2023-03-30]: https://github.com/latex3/latex3/compare/2023-01-16...2023-03-30 +[2023-01-16]: https://github.com/latex3/latex3/compare/2022-10-26...2023-01-16 +[2022-10-26]: https://github.com/latex3/latex3/compare/2022-09-28...2022-10-26 +[2022-09-28]: https://github.com/latex3/latex3/compare/2022-08-30...2022-09-28 +[2022-08-30]: https://github.com/latex3/latex3/compare/2022-08-23...2022-08-30 +[2022-08-23]: https://github.com/latex3/latex3/compare/2022-08-05...2022-08-23 +[2022-08-05]: https://github.com/latex3/latex3/compare/2022-07-01...2022-08-05 +[2022-07-01]: https://github.com/latex3/latex3/compare/2022-04-20...2022-07-01 +[2022-04-20]: https://github.com/latex3/latex3/compare/2022-04-14...2022-04-20 +[2022-04-14]: https://github.com/latex3/latex3/compare/2022-04-10...2022-04-14 +[2022-04-10]: https://github.com/latex3/latex3/compare/2022-02-07...2022-04-10 +[2022-02-07]: https://github.com/latex3/latex3/compare/2022-01-12...2022-02-07 +[2022-01-12]: https://github.com/latex3/latex3/compare/2021-12-14...2022-01-12 +[2021-12-14]: https://github.com/latex3/latex3/compare/2021-10-17...2021-12-14 +[2021-10-17]: https://github.com/latex3/latex3/compare/2021-10-12...2021-10-17 +[2021-10-12]: https://github.com/latex3/latex3/compare/2021-08-04...2021-10-12 +[2021-08-04]: https://github.com/latex3/latex3/compare/2021-07-12...2021-08-04 +[2021-07-12]: https://github.com/latex3/latex3/compare/2021-05-07...2021-07-12 +[2021-05-07]: https://github.com/latex3/latex3/compare/2021-03-18...2021-05-07 +[2021-03-18]: https://github.com/latex3/latex3/compare/2021-03-02...2021-03-18 +[2021-03-02]: https://github.com/latex3/latex3/compare/2021-02-18...2021-03-02 +[2021-02-18]: https://github.com/latex3/latex3/compare/2021-02-06...2021-02-18 +[2021-02-06]: https://github.com/latex3/latex3/compare/2021-01-29...2021-02-06 +[2021-01-29]: https://github.com/latex3/latex3/compare/2021-01-09...2021-01-29 +[2021-01-09]: https://github.com/latex3/latex3/compare/2020-09-24...2021-01-09 +[2020-09-24]: https://github.com/latex3/latex3/compare/2020-09-11...2020-09-24 +[2020-09-11]: https://github.com/latex3/latex3/compare/2020-09-01...2020-09-11 +[2020-09-01]: https://github.com/latex3/latex3/compare/2020-08-07...2020-09-01 +[2020-08-07]: https://github.com/latex3/latex3/compare/2020-06-29...2020-08-07 +[2020-06-29]: https://github.com/latex3/latex3/compare/2020-06-23...2020-06-29 +[2020-06-23]: https://github.com/latex3/latex3/compare/2020-06-18...2020-06-23 +[2020-06-18]: https://github.com/latex3/latex3/compare/2020-06-03...2020-06-18 +[2020-06-03]: https://github.com/latex3/latex3/compare/2020-05-05...2020-06-03 +[2020-05-05]: https://github.com/latex3/latex3/compare/2020-03-12...2020-05-05 +[2020-03-12]: https://github.com/latex3/latex3/compare/2020-02-23...2020-03-12 +[2020-02-23]: https://github.com/latex3/latex3/compare/2020-02-21...2020-02-23 +[2020-02-21]: https://github.com/latex3/latex3/compare/2020-02-03...2020-02-21 +[2020-02-03]: https://github.com/latex3/latex3/compare/2019-11-25...2020-02-03 +[2019-11-25]: https://github.com/latex3/latex3/compare/2019-10-11...2019-11-25 +[2019-10-11]: https://github.com/latex3/latex3/compare/2019-09-05...2019-10-11 +[2019-09-05]: https://github.com/latex3/latex3/compare/2019-08-25...2019-09-05 +[2019-08-25]: https://github.com/latex3/latex3/compare/2019-07-01...2019-08-25 +[2019-07-01]: https://github.com/latex3/latex3/compare/2019-05-28...2019-07-01 diff --git a/Master/texmf-dist/doc/latex-dev/l3backend/README.md b/Master/texmf-dist/doc/latex-dev/l3backend/README.md new file mode 100644 index 00000000000..058fa63cc2a --- /dev/null +++ b/Master/texmf-dist/doc/latex-dev/l3backend/README.md @@ -0,0 +1,16 @@ +LaTeX3 Backend Drivers +====================== + +Release 2024-04-11 + +This package forms parts of `expl3`, and contains the code used to interface +with backends (drivers) across the `expl3` codebase. The functions here are +defined differently depending on the engine in use. As such, these are +distributed separately from `l3kernel` to allow this code to be updated +on an independent schedule. + +----- + +

Copyright (C) 2019-2024 The LaTeX Project
+http://latex-project.org/
+All rights reserved.

diff --git a/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.pdf b/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.pdf new file mode 100644 index 00000000000..ce6b00698f9 Binary files /dev/null and b/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.pdf differ diff --git a/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.tex b/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.tex new file mode 100644 index 00000000000..df0dd0ea8cd --- /dev/null +++ b/Master/texmf-dist/doc/latex-dev/l3backend/l3backend-code.tex @@ -0,0 +1,63 @@ +\iffalse meta-comment + +File: l3backend-code.tex + +Copyright (C) 2019,2021 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 released version of this bundle is available from CTAN. + +----------------------------------------------------------------------- + +The development version of the bundle can be found at + + https://github.com/latex3/latex3 + +for those people who are interested. + +\fi + +\documentclass[full,kernel]{l3doc} + +\begin{document} + +\makeatletter +\let\DelayPrintIndex\PrintIndex +\let\PrintIndex\@empty +\makeatother + +\ExplSyntaxOn +\clist_gput_right:Nn \g_docinput_clist + { + l3backend-basics.dtx , + l3backend-box.dtx , + l3backend-color.dtx , + l3backend-draw.dtx , + l3backend-graphics.dtx , + l3backend-pdf.dtx , + l3backend-opacity.dtx , + l3backend-header.dtx + } +\ExplSyntaxOff + +\part{Implementation} + +\def\maketitle{} +\EnableImplementation +\DisableDocumentation +\DocInputAgain + +\clearpage + +\DelayPrintIndex + +\end{document} diff --git a/Master/texmf-dist/source/latex-dev/l3backend/l3backend-basics.dtx b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-basics.dtx new file mode 100644 index 00000000000..fbac5033179 --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-basics.dtx @@ -0,0 +1,497 @@ +% \iffalse meta-comment +% +%% File: l3backend-basics.dtx +% +% Copyright (C) 2019-2024 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} +% +% \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 2024-04-11} +% +% \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}{2024-04-11}{} + {L3 backend support: dvipdfmx} +% +%<*dvips> + {l3backend-dvips.def}{2024-04-11}{} + {L3 backend support: dvips} +% +%<*dvisvgm> + {l3backend-dvisvgm.def}{2024-04-11}{} + {L3 backend support: dvisvgm} +% +%<*luatex> + {l3backend-luatex.def}{2024-04-11}{} + {L3 backend support: PDF output (LuaTeX)} +% +%<*pdftex> + {l3backend-pdftex.def}{2024-04-11}{} + {L3 backend support: PDF output (pdfTeX)} +% +%<*xetex> + {l3backend-xetex.def}{2024-04-11}{} + {L3 backend support: 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} +% {l3backend-dvipdfmx.def} +% {l3backend-dvips.def} +% {l3backend-dvisvgm.def} +% {l3backend-luatex.def} +% {l3backend-pdftex.def} +% {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 behaviour +% 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} +% +% \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 +% +%<*pdftex> + \tex_pdfliteral:D +% + { \exp_not:n {#1} } + } +\cs_generate_variant:Nn \__kernel_backend_literal_pdf:n { e } +% \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 ~ +% +%<*pdftex> + \tex_pdfliteral:D +% + page { \exp_not:n {#1} } + } +\cs_new_protected:Npn \__kernel_backend_literal_page:e #1 + { +%<*luatex> + \tex_pdfextension:D literal ~ +% +%<*pdftex> + \tex_pdfliteral:D +% + 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: +% +%<*pdftex> + \tex_pdfsave:D +% + } +\cs_new_protected:Npn \__kernel_backend_scope_end: + { +%<*luatex> + \tex_pdfextension:D restore \scan_stop: +% +%<*pdftex> + \tex_pdfrestore:D +% + } +% \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 +% +%<*pdftex> + \tex_pdfsetmatrix:D +% + { \exp_not:n {#1} } + } +\cs_generate_variant:Nn \__kernel_backend_matrix:n { e } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \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} +% +% \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 { } + \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 { } } + \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 { } + \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 { } + \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} +% +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex-dev/l3backend/l3backend-box.dtx b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-box.dtx new file mode 100644 index 00000000000..93d83293ef8 --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-box.dtx @@ -0,0 +1,470 @@ +% \iffalse meta-comment +% +%% File: l3backend-box.dtx +% +% Copyright (C) 2019-2024 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} +% +% \fi +% +% \title{^^A +% The \pkg{l3backend-box} package\\ Backend box support^^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 2024-04-11} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3backend-box} implementation} +% +% \begin{macrocode} +%<*package> +%<@@=box> +% \end{macrocode} +% +% \subsection{\texttt{dvips} backend} +% +% \begin{macrocode} +%<*dvips> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_clip:N} +% The \texttt{dvips} backend scales all absolute dimensions based on the +% output resolution selected and any \TeX{} magnification. Thus for any +% operation involving absolute lengths there is a correction to make. See +% \texttt{normalscale} from \texttt{special.pro} for the variables, noting +% that here everything is saved on the stack rather than as a separate +% variable. Once all of that is done, the actual clipping is trivial. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_clip:N #1 + { + \__kernel_backend_scope_begin: + \__kernel_backend_align_begin: + \__kernel_backend_literal_postscript:n { matrix~currentmatrix } + \__kernel_backend_literal_postscript:n + { Resolution~72~div~VResolution~72~div~scale } + \__kernel_backend_literal_postscript:n { DVImag~dup~scale } + \__kernel_backend_literal_postscript:e + { + 0 ~ + \dim_to_decimal_in_bp:n { \box_dp:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ + \dim_to_decimal_in_bp:n { -\box_ht:N #1 - \box_dp:N #1 } ~ + rectclip + } + \__kernel_backend_literal_postscript:n { setmatrix } + \__kernel_backend_align_end: + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + \skip_horizontal:n { \box_wd:N #1 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_rotate:Nn} +% \begin{macro}{\@@_backend_rotate_aux:Nn} +% Rotating using \texttt{dvips} does not require that the box dimensions +% are altered and has a very convenient built-in operation. Zero rotation +% must be written as |0| not |-0| so there is a quick test. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_rotate:Nn #1#2 + { \exp_args:NNf \@@_backend_rotate_aux:Nn #1 { \fp_eval:n {#2} } } +\cs_new_protected:Npn \@@_backend_rotate_aux:Nn #1#2 + { + \__kernel_backend_scope_begin: + \__kernel_backend_align_begin: + \__kernel_backend_literal_postscript:e + { + \fp_compare:nNnTF {#2} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( -(#2) , 5 ) } } ~ + rotate + } + \__kernel_backend_align_end: + \box_use:N #1 + \__kernel_backend_scope_end: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_scale:Nnn} +% The \texttt{dvips} backend once again has a dedicated operation we can +% use here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_scale:Nnn #1#2#3 + { + \__kernel_backend_scope_begin: + \__kernel_backend_align_begin: + \__kernel_backend_literal_postscript:e + { + \fp_eval:n { round ( #2 , 5 ) } ~ + \fp_eval:n { round ( #3 , 5 ) } ~ + scale + } + \__kernel_backend_align_end: + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\LuaTeX{} and \pdfTeX{} backends} +% +% \begin{macrocode} +%<*luatex|pdftex> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_clip:N} +% The general method is to save the current location, define a clipping path +% equivalent to the bounding box, then insert the content at the current +% position and in a zero width box. The \enquote{real} width is then made up +% using a horizontal skip before tidying up. There are other approaches that +% can be taken (for example using XForm objects), but the logic here shares +% as much code as possible and uses the same conversions (and so same +% rounding errors) in all cases. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_clip:N #1 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal_pdf:e + { + 0~ + \dim_to_decimal_in_bp:n { -\box_dp:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~ + re~W~n + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + \skip_horizontal:n { \box_wd:N #1 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_rotate:Nn} +% \begin{macro}{\@@_backend_rotate_aux:Nn} +% \begin{variable}{\l_@@_backend_cos_fp, \l_@@_backend_sin_fp} +% Rotations are set using an affine transformation matrix which therefore +% requires sine/cosine values not the angle itself. We store the rounded +% values to avoid rounding twice. There are also a couple of comparisons to +% ensure that |-0| is not written to the output, as this avoids any issues +% with problematic display programs. Note that numbers are compared to~$0$ +% after rounding. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_rotate:Nn #1#2 + { \exp_args:NNf \@@_backend_rotate_aux:Nn #1 { \fp_eval:n {#2} } } +\cs_new_protected:Npn \@@_backend_rotate_aux:Nn #1#2 + { + \__kernel_backend_scope_begin: + \box_set_wd:Nn #1 { 0pt } + \fp_set:Nn \l_@@_backend_cos_fp { round ( cosd ( #2 ) , 5 ) } + \fp_compare:nNnT \l_@@_backend_cos_fp = \c_zero_fp + { \fp_zero:N \l_@@_backend_cos_fp } + \fp_set:Nn \l_@@_backend_sin_fp { round ( sind ( #2 ) , 5 ) } + \__kernel_backend_matrix:e + { + \fp_use:N \l_@@_backend_cos_fp \c_space_tl + \fp_compare:nNnTF \l_@@_backend_sin_fp = \c_zero_fp + { 0~0 } + { + \fp_use:N \l_@@_backend_sin_fp + \c_space_tl + \fp_eval:n { -\l_@@_backend_sin_fp } + } + \c_space_tl + \fp_use:N \l_@@_backend_cos_fp + } + \box_use:N #1 + \__kernel_backend_scope_end: + } +\fp_new:N \l_@@_backend_cos_fp +\fp_new:N \l_@@_backend_sin_fp +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_scale:Nnn} +% The same idea as for rotation but without the complexity of signs and +% cosines. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_scale:Nnn #1#2#3 + { + \__kernel_backend_scope_begin: + \__kernel_backend_matrix:e + { + \fp_eval:n { round ( #2 , 5 ) } ~ + 0~0~ + \fp_eval:n { round ( #3 , 5 ) } + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\texttt{dvipdfmx}/\XeTeX{} backend} +% +% \begin{macrocode} +%<*dvipdfmx|xetex> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_clip:N} +% The code here is identical to that for \LuaTeX{}/\pdfTeX{}: unlike rotation and +% scaling, there is no higher-level support in the backend for clipping. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_clip:N #1 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal_pdf:e + { + 0~ + \dim_to_decimal_in_bp:n { -\box_dp:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~ + re~W~n + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + \skip_horizontal:n { \box_wd:N #1 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_rotate:Nn} +% \begin{macro}{\@@_backend_rotate_aux:Nn} +% Rotating in \texttt{dvipdmfx}/\XeTeX{} can be implemented using either PDF or +% backend-specific code. The former approach however is not \enquote{aware} +% of the content of boxes: this means that any embedded links would not be +% adjusted by the rotation. As such, the backend-native approach is preferred: +% the code therefore is similar (though not identical) to the \texttt{dvips} +% version (notice the rotation angle here is positive). As for +% \texttt{dvips}, zero rotation is written as |0| not |-0|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_rotate:Nn #1#2 + { \exp_args:NNf \@@_backend_rotate_aux:Nn #1 { \fp_eval:n {#2} } } +\cs_new_protected:Npn \@@_backend_rotate_aux:Nn #1#2 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal:e + { + x:rotate~ + \fp_compare:nNnTF {#2} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( #2 , 5 ) } } + } + \box_use:N #1 + \__kernel_backend_scope_end: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_scale:Nnn} +% Much the same idea for scaling: use the higher-level backend operation to allow +% for box content. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_scale:Nnn #1#2#3 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal:e + { + x:scale~ + \fp_eval:n { round ( #2 , 5 ) } ~ + \fp_eval:n { round ( #3 , 5 ) } + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\texttt{dvisvgm} backend} +% +% \begin{macrocode} +%<*dvisvgm> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_clip:N} +% \begin{variable}{\g__kernel_clip_path_int} +% Clipping in SVG is more involved than with other backends. The first issue +% is that the clipping path must be defined separately from where it is used, +% so we need to track how many paths have applied. The naming here uses +% \texttt{l3cp} as the namespace with a number following. Rather than use +% a rectangular operation, we define the path manually as this allows it to +% have a depth: easier than the alternative approach of shifting content +% up and down using scopes to allow for the depth of the \TeX{} box and +% keep the reference point the same! +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_clip:N #1 + { + \int_gincr:N \g__kernel_clip_path_int + \__kernel_backend_literal_svg:e + { < clipPath~id = " l3cp \int_use:N \g__kernel_clip_path_int " > } + \__kernel_backend_literal_svg:e + { + < + path ~ d = + " + M ~ 0 ~ + \dim_to_decimal:n { -\box_dp:N #1 } ~ + L ~ \dim_to_decimal:n { \box_wd:N #1 } ~ + \dim_to_decimal:n { -\box_dp:N #1 } ~ + L ~ \dim_to_decimal:n { \box_wd:N #1 } ~ + \dim_to_decimal:n { \box_ht:N #1 + \box_dp:N #1 } ~ + L ~ 0 ~ + \dim_to_decimal:n { \box_ht:N #1 + \box_dp:N #1 } ~ + Z + " + /> + } + \__kernel_backend_literal_svg:n + { < /clipPath > } +% \end{macrocode} +% In general the SVG set up does not try to transform coordinates to the +% current point. For clipping we need to do that, so have a transformation +% here to get us to the right place, and a matching one just before the +% \TeX{} box is inserted to get things back on track. The clip path needs to +% come between those two such that if lines up with the current point, as +% does the \TeX{} box. +% \begin{macrocode} + \__kernel_backend_scope_begin:n + { + transform = + " + translate ( { ?x } , { ?y } ) ~ + scale ( 1 , -1 ) + " + } + \__kernel_backend_scope:e + { + clip-path = + "url ( \c_hash_str l3cp \int_use:N \g__kernel_clip_path_int ) " + } + \__kernel_backend_scope:n + { + transform = + " + scale ( -1 , 1 ) ~ + translate ( { ?x } , { ?y } ) ~ + scale ( -1 , -1 ) + " + } + \box_use:N #1 + \__kernel_backend_scope_end: + } +\int_new:N \g__kernel_clip_path_int +% \end{macrocode} +% \end{variable} +% \end{macro} +% +% \begin{macro}{\@@_backend_rotate:Nn} +% Rotation has a dedicated operation which includes a centre-of-rotation +% optional pair. That can be picked up from the backend syntax, so there is +% no need to worry about the transformation matrix. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_rotate:Nn #1#2 + { + \__kernel_backend_scope_begin:e + { + transform = + " + rotate + ( \fp_eval:n { round ( -(#2) , 5 ) } , ~ { ?x } , ~ { ?y } ) + " + } + \box_use:N #1 + \__kernel_backend_scope_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_scale:Nnn} +% In contrast to rotation, we have to account for the current position in this +% case. That is done using a couple of translations in addition to the scaling +% (which is therefore done backward with a flip). +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_scale:Nnn #1#2#3 + { + \__kernel_backend_scope_begin:e + { + transform = + " + translate ( { ?x } , { ?y } ) ~ + scale + ( + \fp_eval:n { round ( -#2 , 5 ) } , + \fp_eval:n { round ( -#3 , 5 ) } + ) ~ + translate ( { ?x } , { ?y } ) ~ + scale ( -1 ) + " + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex-dev/l3backend/l3backend-color.dtx b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-color.dtx new file mode 100644 index 00000000000..307432d554f --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-color.dtx @@ -0,0 +1,1356 @@ +% \iffalse meta-comment +% +%% File: l3backend-color.dtx +% +% Copyright (C) 2019-2024 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} +% +% \fi +% +% \title{^^A +% The \pkg{l3backend-color} module\\ Backend color support^^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 2024-04-11} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3backend-color} implementation} +% +% \begin{macrocode} +%<*package> +%<@@=color> +% \end{macrocode} +% +% Color support is split into parts: collecting data from \LaTeXe{}, the color +% stack, general color, separations, and color for drawings. We have different +% approaches in each backend, and have some choices to make about +% \texttt{dvipdfmx}/\XeTeX{} in particular. Whilst it is in some ways +% convenient to use the same approach in multiple backends, the fact that +% \texttt{dvipdfmx}/\XeTeX{} is PDF-based means it (largely) sticks closer to +% direct PDF output. +% +% \subsection{The color stack} +% +% For PDF-based engines, we have a color stack available inside the specials. +% This is used for concepts beyond color itself: it is needed to manage the +% graphics state generally. Although \texttt{dvipdfmx}/\XeTeX{} have multiple +% color stacks in recent releases, the way these interact with the original +% single stack and with other graphic state operations means that currently it +% is not feasible to use the multiple stacks. +% +% \subsubsection{Common code} +% +% \begin{macrocode} +%<*luatex|pdftex> +% \end{macrocode} +% +% \begin{variable}{\l_@@_backend_stack_int} +% For tracking which stack is in use where multiple stacks are used: +% currently just \pdfTeX{}/\LuaTeX{} but at some future stage may also cover +% \texttt{dvipdfmx}/\XeTeX{}. +% \begin{macrocode} +\int_new:N \l_@@_backend_stack_int +% \end{macrocode} +% \end{variable} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{\LuaTeX and \pdfTeX{}} +% +% \begin{macrocode} +%<*luatex|pdftex> +% \end{macrocode} +% +% \begin{macro}{\__kernel_color_backend_stack_init:Nnn} +% \begin{macrocode} +\cs_new_protected:Npn \__kernel_color_backend_stack_init:Nnn #1#2#3 + { + \int_const:Nn #1 + { +%<*luatex> + \tex_pdffeedback:D colorstackinit ~ +% +%<*pdftex> + \tex_pdfcolorstackinit:D +% + \tl_if_blank:nF {#2} { #2 ~ } + {#3} + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\__kernel_color_backend_stack_push:nn} +% \begin{macro}{\__kernel_color_backend_stack_pop:n} +% \begin{macrocode} +\cs_new_protected:Npn \__kernel_color_backend_stack_push:nn #1#2 + { +%<*luatex> + \tex_pdfextension:D colorstack ~ +% +%<*pdftex> + \tex_pdfcolorstack:D +% + \int_eval:n {#1} ~ push ~ {#2} + } +\cs_new_protected:Npn \__kernel_color_backend_stack_pop:n #1 + { +%<*luatex> + \tex_pdfextension:D colorstack ~ +% +%<*pdftex> + \tex_pdfcolorstack:D +% + \int_eval:n {#1} ~ pop \scan_stop: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{General color} +% +% \subsubsection{\texttt{dvips}-style} +% +% \begin{macrocode} +%<*dvips|dvisvgm> +% \end{macrocode} +% +% \begin{macro} +% { +% \@@_backend_select_cmyk:n , +% \@@_backend_select_gray:n , +% \@@_backend_select_named:n , +% \@@_backend_select_rgb:n , +% \@@_backend_select:n +% } +% \begin{macro}{\@@_backend_reset:} +% Push the data to the stack. In the case of \texttt{dvips} also saves the +% drawing color in raw PostScript. The |spot| model is for handling data +% in classical format. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select_cmyk:n #1 + { \@@_backend_select:n { cmyk ~ #1 } } +\cs_new_protected:Npn \@@_backend_select_gray:n #1 + { \@@_backend_select:n { gray ~ #1 } } +\cs_new_protected:Npn \@@_backend_select_named:n #1 + { \@@_backend_select:n { ~ #1 } } +\cs_new_protected:Npn \@@_backend_select_rgb:n #1 + { \@@_backend_select:n { rgb ~ #1 } } +\cs_new_protected:Npn \@@_backend_select:n #1 + { + \__kernel_backend_literal:n { color~push~ #1 } +%<*dvips> + \__kernel_backend_postscript:n { /color.sc ~ { } ~ def } +% + } +\cs_new_protected:Npn \@@_backend_reset: + { \__kernel_backend_literal:n { color~pop } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{\LuaTeX{} and \pdfTeX{}} +% +% \begin{macrocode} +%<*luatex|pdftex> +% \end{macrocode} +% +% \begin{variable}{\l_@@_backend_fill_tl, \l_@@_backend_stroke_tl} +% \begin{macrocode} +\tl_new:N \l_@@_backend_fill_tl +\tl_new:N \l_@@_backend_stroke_tl +\tl_set:Nn \l_@@_backend_fill_tl { 0 ~ g } +\tl_set:Nn \l_@@_backend_stroke_tl { 0 ~ G } +% \end{macrocode} +% \end{variable} +% +% \begin{macro} +% { +% \@@_backend_select_cmyk:n , +% \@@_backend_select_gray:n , +% \@@_backend_select_rgb:n +% } +% \begin{macro}{\@@_backend_select:nn} +% \begin{macro}{\@@_backend_reset:} +% Store the values then pass to the stack. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select_cmyk:n #1 + { \@@_backend_select:nn { #1 ~ k } { #1 ~ K } } +\cs_new_protected:Npn \@@_backend_select_gray:n #1 + { \@@_backend_select:nn { #1 ~ g } { #1 ~ G } } +\cs_new_protected:Npn \@@_backend_select_rgb:n #1 + { \@@_backend_select:nn { #1 ~ rg } { #1 ~ RG } } +\cs_new_protected:Npn \@@_backend_select:nn #1#2 + { + \tl_set:Nn \l_@@_backend_fill_tl {#1} + \tl_set:Nn \l_@@_backend_stroke_tl {#2} + \__kernel_color_backend_stack_push:nn \l_@@_backend_stack_int { #1 ~ #2 } + } +\cs_new_protected:Npn \@@_backend_reset: + { \__kernel_color_backend_stack_pop:n \l_@@_backend_stack_int } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsubsection{\texttt{dvipmdfx}/\XeTeX{}} +% +% These backends have the most possible approaches: it recognises both +% \texttt{dvips}-based color specials and its own format, plus one can +% include PDF statements directly. Recent releases also have a color stack +% approach similar to \pdfTeX{}. Of the stack methods, the dedicated +% the most versatile is the latter as it can cover all of the use cases +% we have. However, at present this interacts problematically with any color +% on the original stack. We therefore stick to a single-stack approach here. +% +% \begin{macrocode} +%<*dvipdfmx|xetex> +% \end{macrocode} +% +% \begin{macro} +% { +% \@@_backend_select:n , +% \@@_backend_select_cmyk:n , +% \@@_backend_select_gray:n , +% \@@_backend_select_rgb:n +% } +% \begin{macro}{\@@_backend_reset:} +% Using the single stack is relatively easy as there is only one route. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select:n #1 + { \__kernel_backend_literal:n { pdf : bc ~ [ #1 ] } } +\cs_new_eq:NN \@@_backend_select_cmyk:n \@@_backend_select:n +\cs_new_eq:NN \@@_backend_select_gray:n \@@_backend_select:n +\cs_new_eq:NN \@@_backend_select_rgb:n \@@_backend_select:n +\cs_new_protected:Npn \@@_backend_reset: + { \__kernel_backend_literal:n { pdf : ec } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_select_named:n} +% For classical named colors, the only value we should get is |Black|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select_named:n #1 + { + \str_if_eq:nnTF {#1} { Black } + { \@@_backend_select_gray:n { 0 } } + { \msg_error:nnn { color } { unknown-named-color } {#1} } + } +\msg_new:nnn { color } { unknown-named-color } + { Named~color~'#1'~is~not~known. } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{Separations} +% +% Here, life gets interesting and we need essentially one approach per +% backend. +% +% \begin{macrocode} +%<*dvipdfmx|luatex|pdftex|xetex|dvips> +% \end{macrocode} +% +% But we start with some functionality needed for both PostScript and +% PDF based backends. +% +% \begin{variable}{\g_@@_backend_colorant_prop} +% \begin{macrocode} +\prop_new:N \g_@@_backend_colorant_prop +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[EXP]{\@@_backend_devicen_colorants:n} +% \begin{macro}[EXP]{\@@_backend_devicen_colorants:w} +% \begin{macrocode} +\cs_new:Npe \@@_backend_devicen_colorants:n #1 + { + \exp_not:N \tl_if_blank:nF {#1} + { + \c_space_tl + << ~ + /Colorants ~ + << ~ + \exp_not:N \@@_backend_devicen_colorants:w #1 ~ + \exp_not:N \q_recursion_tail \c_space_tl + \exp_not:N \q_recursion_stop + >> ~ + >> + } + } +\cs_new:Npn \@@_backend_devicen_colorants:w #1 ~ + { + \quark_if_recursion_tail_stop:n {#1} + \prop_if_in:NnT \g_@@_backend_colorant_prop {#1} + { + #1 ~ + \prop_item:Nn \g_@@_backend_colorant_prop {#1} ~ + } + \@@_backend_devicen_colorants:w + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dvips> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_select_separation:nn, \@@_backend_select_devicen:nn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select_separation:nn #1#2 + { \@@_backend_select:n { separation ~ #1 ~ #2 } } +\cs_new_eq:NN \@@_backend_select_devicen:nn \@@_backend_select_separation:nn +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_select_iccbased:nn} +% No support. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select_iccbased:nn #1#2 { } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_separation_init:nnnnn, +% \@@_backend_separation_init:neenn +% } +% \begin{macro} +% {\@@_backend_separation_init_aux:nnnnnn} +% \begin{macro}[EXP] +% { +% \@@_backend_separation_init_/DeviceCMYK:nnn , +% \@@_backend_separation_init_/DeviceGray:nnn , +% \@@_backend_separation_init_/DeviceRGB:nnn +% } +% \begin{macro}[EXP]{\@@_backend_separation_init_Device:Nn} +% \begin{macro}[EXP]{\@@_backend_separation_init:nnn} +% \begin{macro}[EXP]{\@@_backend_separation_init_count:n} +% \begin{macro}[EXP]{\@@_backend_separation_init_count:w} +% \begin{macro}[EXP]{\@@_backend_separation_init:nnnn} +% \begin{macro}[EXP]{\@@_backend_separation_init:w} +% \begin{macro}[EXP]{\@@_backend_separation_init:n} +% \begin{macro}[EXP]{\@@_backend_separation_init:nw} +% \begin{macro}{\@@_backend_separation_init_CIELAB:nnn} +% Initialising here means creating a small header set up plus massaging +% some data. This comes about as we have to deal with PDF-focussed data, +% which makes most sense \enquote{higher-up}. The approach is based on +% ideas from \url{https://tex.stackexchange.com/q/560093} plus using +% the PostScript manual for other aspects. +% \begin{macrocode} +\cs_new_protected:Npe \@@_backend_separation_init:nnnnn #1#2#3#4#5 + { + \bool_if:NT \g__kernel_backend_header_bool + { + \exp_not:N \exp_args:Ne \__kernel_backend_first_shipout:n + { + \exp_not:N \@@_backend_separation_init_aux:nnnnnn + { \exp_not:N \int_use:N \g_@@_model_int } + {#1} {#2} {#3} {#4} {#5} + } + \prop_gput:Nee \exp_not:N \g_@@_backend_colorant_prop + { / \exp_not:N \str_convert_pdfname:n {#1} } + { + << ~ + /setcolorspace ~ {} ~ + >> ~ begin ~ + color \exp_not:N \int_use:N \g_@@_model_int \c_space_tl + end + } + } + } +\cs_generate_variant:Nn \@@_backend_separation_init:nnnnn { nee } +\cs_new_protected:Npn \@@_backend_separation_init_aux:nnnnnn #1#2#3#4#5#6 + { + \__kernel_backend_literal:e + { + ! + TeXDict ~ begin ~ + /color #1 + { + [ ~ + /Separation ~ ( \str_convert_pdfname:n {#2} ) ~ + [ ~ #3 ~ ] ~ + { + \cs_if_exist_use:cF { @@_backend_separation_init_ #3 :nnn } + { \@@_backend_separation_init:nnn } + {#4} {#5} {#6} + } + ] ~ setcolorspace + } ~ def ~ + end + } + } +\cs_new:cpn { @@_backend_separation_init_ /DeviceCMYK :nnn } #1#2#3 + { \@@_backend_separation_init_Device:Nn 4 {#3} } +\cs_new:cpn { @@_backend_separation_init_ /DeviceGray :nnn } #1#2#3 + { \@@_backend_separation_init_Device:Nn 1 {#3} } +\cs_new:cpn { @@_backend_separation_init_ /DeviceRGB :nnn } #1#2#3 + { \@@_backend_separation_init_Device:Nn 2 {#3} } +\cs_new:Npn \@@_backend_separation_init_Device:Nn #1#2 + { + #2 ~ + \prg_replicate:nn {#1} + { #1 ~ index ~ mul ~ #1 ~ 1 ~ roll ~ } + \int_eval:n { #1 + 1 } ~ -1 ~ roll ~ pop + } +% \end{macrocode} +% For the generic case, we cannot use |/FunctionType 2| unfortunately, so +% we have to code that idea up in PostScript. Here, we will therefore assume +% that a range is \emph{always} given. First, we count values in each argument: +% at the backend level, we can assume there are always well-behaved with +% spaces present. +% \begin{macrocode} +\cs_new:Npn \@@_backend_separation_init:nnn #1#2#3 + { + \exp_args:Ne \@@_backend_separation_init:nnnn + { \@@_backend_separation_init_count:n {#2} } + {#1} {#2} {#3} + } +\cs_new:Npn \@@_backend_separation_init_count:n #1 + { \int_eval:n { 0 \@@_backend_separation_init_count:w #1 ~ \s_@@_stop } } +\cs_new:Npn \@@_backend_separation_init_count:w #1 ~ #2 \s_@@_stop + { + +1 + \tl_if_blank:nF {#2} + { \@@_backend_separation_init_count:w #2 \s_@@_stop } + } +% \end{macrocode} +% Now we implement the algorithm. In the terms in the PostScript manual, +% we have $\mathbf{N} = 1$ and $\mathbf{Domain} = [0~1]$, with +% $\mathbf{Range}$ as |#2|, $\mathbf{C0}$ as |#3| and $\mathbf{C1}$ +% as |#4|, with the number of output components in |#1|. So all we have +% to do is implement $y_{i} = \mathbf{C0}_{i} + x(\mathbf{C1}_{i} - +% \mathbf{C0}_{i})$ with lots of stack manipulation, then check the +% ranges. That's done by adding everything to the stack first, then using +% the fact we know all of the offsets. As manipulating the stack is tricky, +% we start by re-formatting the $\mathbf{C0}$ and $\mathbf{C1}$ arrays to +% be interleaved, and add a \texttt{0} to each pair: this is used +% to keep the stack of constant length while we are doing the first pass of +% mathematics. We then working through that list, calculating from the +% last to the first value before tidying up by removing all of the input +% values. We do that by first copying all of the final $y$ values to the +% end of the stack, then rolling everything so we can pop the now-unneeded +% material. +% \begin{macrocode} +\cs_new:Npn \@@_backend_separation_init:nnnn #1#2#3#4 + { + \@@_backend_separation_init:w #3 ~ \s_@@_stop #4 ~ \s_@@_stop + \prg_replicate:nn {#1} + { + pop ~ 1 ~ index ~ neg ~ 1 ~ index ~ add ~ + \int_eval:n { 3 * #1 } ~ index ~ mul ~ + 2 ~ index ~ add ~ + \int_eval:n { 3 * #1 } ~ #1 ~ roll ~ + } + \int_step_function:nnnN {#1} { -1 } { 1 } + \@@_backend_separation_init:n + \int_eval:n { 4 * #1 + 1 } ~ #1 ~ roll ~ + \prg_replicate:nn { 3 * #1 + 1 } { pop ~ } + \tl_if_blank:nF {#2} + { \@@_backend_separation_init:nw {#1} #2 ~ \s_@@_stop } + } +\cs_new:Npn \@@_backend_separation_init:w + #1 ~ #2 \s_@@_stop #3 ~ #4 \s_@@_stop + { + #1 ~ #3 ~ 0 ~ + \tl_if_blank:nF {#2} + { \@@_backend_separation_init:w #2 \s_@@_stop #4 \s_@@_stop } + } +\cs_new:Npn \@@_backend_separation_init:n #1 + { \int_eval:n { #1 * 2 } ~ index ~ } +% \end{macrocode} +% Finally, we deal with the range limit if required. This is handled +% by splitting the range into pairs. It's then just a question of doing +% the comparisons, this time dropping everything except the desired +% result. +% \begin{macrocode} +\cs_new:Npn \@@_backend_separation_init:nw #1#2 ~ #3 ~ #4 \s_@@_stop + { + #2 ~ #3 ~ + 2 ~ index ~ 2 ~ index ~ lt ~ + { ~ pop ~ exch ~ pop ~ } ~ + { ~ + 2 ~ index ~ 1 ~ index ~ gt ~ + { ~ exch ~ pop ~ exch ~ pop ~ } ~ + { ~ pop ~ pop ~ } ~ + ifelse ~ + } + ifelse ~ + #1 ~ 1 ~ roll ~ + \tl_if_blank:nF {#4} + { \@@_backend_separation_init:nw {#1} #4 \s_@@_stop } + } +% \end{macrocode} +% CIELAB support uses the detail from the PostScript reference, page 227; +% other than that block of PostScript, this is the same as for PDF-based +% routes. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_separation_init_CIELAB:nnn #1#2#3 + { + \@@_backend_separation_init:neenn + {#2} + { + /CIEBasedABC ~ + << ~ + /RangeABC ~ [ ~ \c_@@_model_range_CIELAB_tl \c_space_tl ] ~ + /DecodeABC ~ + [ ~ + { ~ 16 ~ add ~ 116 ~ div ~ } ~ bind ~ + { ~ 500 ~ div ~ } ~ bind ~ + { ~ 200 ~ div ~ } ~ bind ~ + ] ~ + /MatrixABC ~ [ ~ 1 ~ 1 ~ 1 ~ 1 ~ 0 ~ 0 ~ 0 ~ 0 ~ -1 ~ ] ~ + /DecodeLMN ~ + [ ~ + { ~ + dup ~ 6 ~ 29 ~ div ~ ge ~ + { ~ dup ~ dup ~ mul ~ mul ~ ~ } ~ + { ~ 4 ~ 29 ~ div ~ sub ~ 108 ~ 841 ~ div ~ mul ~ } ~ + ifelse ~ + 0.9505 ~ mul ~ + } ~ bind ~ + { ~ + dup ~ 6 ~ 29 ~ div ~ ge ~ + { ~ dup ~ dup ~ mul ~ mul ~ } ~ + { ~ 4 ~ 29 ~ div ~ sub ~ 108 ~ 841 ~ div ~ mul ~ } ~ + ifelse ~ + } ~ bind ~ + { ~ + dup ~ 6 ~ 29 ~ div ~ ge ~ + { ~ dup ~ dup ~ mul ~ mul ~ } ~ + { ~ 4 ~ 29 ~ div ~ sub ~ 108 ~ 841 ~ div ~ mul ~ } ~ + ifelse ~ + 1.0890 ~ mul ~ + } ~ bind + ] ~ + /WhitePoint ~ + [ ~ \tl_use:c { c_@@_model_whitepoint_CIELAB_ #1 _tl } ~ ] ~ + >> + } + { \c_@@_model_range_CIELAB_tl } + { 100 ~ 0 ~ 0 } + {#3} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_devicen_init:nnn} +% Trivial as almost all of the work occurs in the shared code. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_devicen_init:nnn #1#2#3 + { + \__kernel_backend_literal:e + { + ! + TeXDict ~ begin ~ + /color \int_use:N \g_@@_model_int + { + [ ~ + /DeviceN ~ + [ ~ #1 ~ ] ~ + #2 ~ + { ~ #3 ~ } ~ + \@@_backend_devicen_colorants:n {#1} + ] ~ setcolorspace + } ~ def ~ + end + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_iccbased_init:nnn} +% No support at present. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_iccbased_init:nnn #1#2#3 { } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dvisvgm> +% \end{macrocode} +% +% \begin{macro} +% { +% \@@_backend_select_separation:nn, +% \@@_backend_select_devicen:nn +% } +% No support at present. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select_separation:nn #1#2 { } +\cs_new_eq:NN \@@_backend_select_devicen:nn \@@_backend_select_separation:nn +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% {\@@_backend_separation_init:nnnnn, \@@_backend_separation_init_CIELAB:nnn} +% No support at present. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_separation_init:nnnnn #1#2#3#4#5 { } +\cs_new_protected:Npn \@@_backend_separation_init_CIELAB:nnnnnn #1#2#3 { } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_select_iccbased:nn} +% As detailed in \url{https://www.w3.org/TR/css-color-4/#at-profile}, +% we can apply a color profile using CSS. As we have a local file, we use +% a relative URL. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select_iccbased:nn #1#2 + { + \__kernel_backend_literal_svg:e + { + + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dvipdfmx|luatex|pdftex|xetex> +% \end{macrocode} +% +% \begin{macro} +% { +% \@@_backend_select_separation:nn, +% \@@_backend_select_devicen:nn , +% \@@_backend_select_iccbased:nn +% } +% \begin{macrocode} +%<*dvipdfmx|xetex> +\cs_new_protected:Npn \@@_backend_select_separation:nn #1#2 + { \__kernel_backend_literal:e { pdf : bc ~ \pdf_object_ref:n {#1} ~ [ #2 ] } } +% +%<*luatex|pdftex> +\cs_new_protected:Npn \@@_backend_select_separation:nn #1#2 + { \@@_backend_select:nn { /#1 ~ cs ~ #2 ~ scn } { /#1 ~ CS ~ #2 ~ SCN } } +% +\cs_new_eq:NN \@@_backend_select_devicen:nn \@@_backend_select_separation:nn +\cs_new_eq:NN \@@_backend_select_iccbased:nn \@@_backend_select_separation:nn +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_init_resource:n} +% Resource initiation comes up a few times. For \texttt{dvipdfmx}/\XeTeX{}, +% we skip this as at present it's handled by the backend. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_init_resource:n #1 + { +%<*luatex|pdftex> + \bool_lazy_and:nnT + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \use:e + { + \pdfmanagement_add:nnn + { Page / Resources / ColorSpace } + { #1 } + { \pdf_object_ref_last: } + } + } +% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_separation_init:nnnnn} +% \begin{macro}{\@@_backend_separation_init:nn} +% \begin{macro}{\@@_backend_separation_init_CIELAB:nnn} +% Initialising the PDF structures needs two parts: creating an object +% containing the \enquote{real} name of the Separation, then adding a reference +% to that to each page. We use a separate object for the tint transformation +% following the model in the PDF reference. The object here for the color +% needs to be named as that way it's accessible to +% \texttt{dvipdfmx}/\XeTeX{}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_separation_init:nnnnn #1#2#3#4#5 + { + \pdf_object_unnamed_write:ne { dict } + { + /FunctionType ~ 2 + /Domain ~ [0 ~ 1] + \tl_if_blank:nF {#3} { /Range ~ [#3] } + /C0 ~ [#4] ~ + /C1 ~ [#5] /N ~ 1 + } + \exp_args:Ne \@@_backend_separation_init:nn + { \str_convert_pdfname:n {#1} } {#2} + \@@_backend_init_resource:n { color \int_use:N \g_@@_model_int } + } +\cs_new_protected:Npn \@@_backend_separation_init:nn #1#2 + { + \use:e + { + \pdf_object_new:n { color \int_use:N \g_@@_model_int } + \pdf_object_write:nnn { color \int_use:N \g_@@_model_int } { array } + { /Separation /#1 ~ #2 ~ \pdf_object_ref_last: } + } + \prop_gput:Nne \g_@@_backend_colorant_prop { /#1 } + { \pdf_object_ref_last: } + } +% \end{macrocode} +% For CIELAB colors, we need one object per document for the illuminant, +% plus initialisation of the color space referencing that object. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_separation_init_CIELAB:nnn #1#2#3 + { + \pdf_object_if_exist:nF { @@_illuminant_CIELAB_ #1 } + { + \pdf_object_new:n { @@_illuminant_CIELAB_ #1 } + \pdf_object_write:nne { @@_illuminant_CIELAB_ #1 } { array } + { + /Lab ~ + << + /WhitePoint ~ + [ \tl_use:c { c_@@_model_whitepoint_CIELAB_ #1 _tl } ] + /Range ~ [ \c_@@_model_range_CIELAB_tl ] + >> + } + } + \@@_backend_separation_init:nnnnn + {#2} + { \pdf_object_ref:n { @@_illuminant_CIELAB_ #1 } } + { \c_@@_model_range_CIELAB_tl } + { 100 ~ 0 ~ 0 } + {#3} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_devicen_init:nnn} +% \begin{macro}[EXP]{\@@_backend_devicen_init:w} +% Similar to the Separations case, but with an arbitrary function for +% the alternative space work. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_devicen_init:nnn #1#2#3 + { + \pdf_object_unnamed_write:ne { stream } + { + { + /FunctionType ~ 4 ~ + /Domain ~ + [ ~ + \prg_replicate:nn + { 0 \@@_backend_devicen_init:w #1 ~ \s_@@_stop } + { 0 ~ 1 ~ } + ] ~ + /Range ~ + [ ~ + \str_case:nn {#2} + { + { /DeviceCMYK } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 } + { /DeviceGray } { 0 ~ 1 } + { /DeviceRGB } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 } + } ~ + ] + } + { {#3} } + } + \use:e + { + \pdf_object_new:n { color \int_use:N \g_@@_model_int } + \pdf_object_write:nnn { color \int_use:N \g_@@_model_int } { array } + { + /DeviceN ~ + [ ~ #1 ~ ] ~ + #2 ~ + \pdf_object_ref_last: + \@@_backend_devicen_colorants:n {#1} + } + } + \@@_backend_init_resource:n { color \int_use:N \g_@@_model_int } + } +\cs_new:Npn \@@_backend_devicen_init:w #1 ~ #2 \s_@@_stop + { + + 1 + \tl_if_blank:nF {#2} + { \@@_backend_devicen_init:w #2 \s_@@_stop } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_iccbased_init:nnn} +% Lots of data to save here: we only want to do that once per file, +% so track it by name. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_iccbased_init:nnn #1#2#3 + { + \pdf_object_if_exist:nF { @@_icc_ #1 } + { + \pdf_object_new:n { @@_icc_ #1 } + \pdf_object_write:nne { @@_icc_ #1 } { fstream } + { + { + /N ~ \exp_not:n { #2 } ~ + \tl_if_empty:nF { #3 } { /Range~[ #3 ] } + } + {#1} + } + } + \pdf_object_unnamed_write:ne { array } + { /ICCBased ~ \pdf_object_ref:n { @@_icc_ #1 } } + \@@_backend_init_resource:n { color \int_use:N \g_@@_model_int } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_iccbased_device:nnn} +% This is very similar to setting up a color space: the only part we +% add to the page resources differently. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_iccbased_device:nnn #1#2#3 + { + \pdf_object_if_exist:nF { @@_icc_ #1 } + { + \pdf_object_new:n { @@_icc_ #1 } + \pdf_object_write:nnn { @@_icc_ #1 } { fstream } + { + { /N ~ #3 } + {#1} + } + } + \pdf_object_unnamed_write:ne { array } + { /ICCBased ~ \pdf_object_ref:n { @@_icc_ #1 } } + \@@_backend_init_resource:n { Default #2 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{Fill and stroke color} +% +% Here, \texttt{dvipdfmx}/\XeTeX{} we write direct PDF specials for the fill, +% and only use the stack for the stroke color (see above for comments on why +% we cannot use multiple stacks with these backends). \LuaTeX{} and \pdfTeX{} +% have mutiple stacks that can deal with fill and stroke. For \texttt{dvips} +% we have to manage fill and stroke color ourselves. We also handle +% \texttt{dvisvgm} independently, as there we can create SVG directly. +% +% \begin{macrocode} +%<*dvipdfmx|xetex> +% \end{macrocode} +% +% \begin{macro} +% { +% \@@_backend_fill:n , +% \@@_backend_fill_cmyk:n , +% \@@_backend_fill_gray:n , +% \@@_backend_fill_rgb:n , +% \@@_backend_stroke:n , +% \@@_backend_stroke_cmyk:n , +% \@@_backend_stroke_gray:n , +% \@@_backend_stroke_rgb:n +% } +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_fill:n #1 + { \__kernel_backend_literal:n { pdf : bc ~ fill ~ [ #1 ] } } +\cs_new_eq:NN \@@_backend_fill_cmyk:n \@@_backend_fill:n +\cs_new_eq:NN \@@_backend_fill_gray:n \@@_backend_fill:n +\cs_new_eq:NN \@@_backend_fill_rgb:n \@@_backend_fill:n +\cs_new_protected:Npn \@@_backend_stroke:n #1 + { \__kernel_backend_literal:n { pdf : bc ~ stroke ~ [ #1 ] } } +\cs_new_eq:NN \@@_backend_stroke_cmyk:n \@@_backend_stroke:n +\cs_new_eq:NN \@@_backend_stroke_gray:n \@@_backend_stroke:n +\cs_new_eq:NN \@@_backend_stroke_rgb:n \@@_backend_stroke:n +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_fill_separation:nn, +% \@@_backend_stroke_separation:nn, +% \@@_backend_fill_devicen:nn, +% \@@_backend_stroke_devicen:nn +% } +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_fill_separation:nn #1#2 + { + \__kernel_backend_literal:e + { pdf : bc ~ fill ~ \pdf_object_ref:n {#1} ~ [ #2 ] } + } +\cs_new_protected:Npn \@@_backend_stroke_separation:nn #1#2 + { + \__kernel_backend_literal:e + { pdf : bc ~ stroke ~ \pdf_object_ref:n {#1} ~ [ #2 ] } + } +\cs_new_eq:NN \@@_backend_fill_devicen:nn \@@_backend_fill_separation:nn +\cs_new_eq:NN \@@_backend_stroke_devicen:nn \@@_backend_stroke_separation:nn +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_fill_reset:, \@@_backend_stroke_reset:} +% \begin{macrocode} +\cs_new_eq:NN \@@_backend_fill_reset: \@@_backend_reset: +\cs_new_eq:NN \@@_backend_stroke_reset: \@@_backend_reset: +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*luatex|pdftex> +% \end{macrocode} +% +% \begin{macro} +% { +% \@@_backend_fill_cmyk:n , +% \@@_backend_fill_gray:n , +% \@@_backend_fill_rgb:n , +% \@@_backend_fill:n , +% \@@_backend_stroke_cmyk:n , +% \@@_backend_stroke_gray:n , +% \@@_backend_stroke_rgb:n , +% \@@_backend_stroke:n +% } +% Drawing (fill/stroke) color is handled in \texttt{dvipdfmx}/\XeTeX{} in the +% same way as \LuaTeX{}/\pdfTeX{}. We use the same approach as earlier, except the +% color stack is not involved so the generic direct PDF operation is used. +% There is no worry about the nature of strokes: everything is handled +% automatically. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_fill_cmyk:n #1 + { \@@_backend_fill:n { #1 ~ k } } +\cs_new_protected:Npn \@@_backend_fill_gray:n #1 + { \@@_backend_fill:n { #1 ~ g } } +\cs_new_protected:Npn \@@_backend_fill_rgb:n #1 + { \@@_backend_fill:n { #1 ~ rg } } +\cs_new_protected:Npn \@@_backend_fill:n #1 + { + \tl_set:Nn \l_@@_backend_fill_tl {#1} + \__kernel_color_backend_stack_push:nn \l_@@_backend_stack_int + { #1 ~ \l_@@_backend_stroke_tl } + } +\cs_new_protected:Npn \@@_backend_stroke_cmyk:n #1 + { \@@_backend_stroke:n { #1 ~ K } } +\cs_new_protected:Npn \@@_backend_stroke_gray:n #1 + { \@@_backend_stroke:n { #1 ~ G } } +\cs_new_protected:Npn \@@_backend_stroke_rgb:n #1 + { \@@_backend_stroke:n { #1 ~ RG } } +\cs_new_protected:Npn \@@_backend_stroke:n #1 + { + \tl_set:Nn \l_@@_backend_stroke_tl {#1} + \__kernel_color_backend_stack_push:nn \l_@@_backend_stack_int + { \l_@@_backend_fill_tl \c_space_tl #1 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_fill_separation:nn, +% \@@_backend_stroke_separation:nn, +% \@@_backend_fill_devicen:nn, +% \@@_backend_stroke_devicen:nn +% } +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_fill_separation:nn #1#2 + { \@@_backend_fill:n { /#1 ~ cs ~ #2 ~ scn } } +\cs_new_protected:Npn \@@_backend_stroke_separation:nn #1#2 + { \@@_backend_stroke:n { /#1 ~ CS ~ #2 ~ SCN } } +\cs_new_eq:NN \@@_backend_fill_devicen:nn \@@_backend_fill_separation:nn +\cs_new_eq:NN \@@_backend_stroke_devicen:nn \@@_backend_stroke_separation:nn +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_fill_reset:, \@@_backend_stroke_reset:} +% \begin{macrocode} +\cs_new_eq:NN \@@_backend_fill_reset: \@@_backend_reset: +\cs_new_eq:NN \@@_backend_stroke_reset: \@@_backend_reset: +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dvips> +% \end{macrocode} +% +% \begin{macro} +% { +% \@@_backend_fill_cmyk:n , +% \@@_backend_fill_gray:n , +% \@@_backend_fill_rgb:n , +% \@@_backend_fill:n , +% \@@_backend_stroke_cmyk:n , +% \@@_backend_stroke_gray:n , +% \@@_backend_stroke_rgb:n +% } +% Fill color here is the same as general color \emph{except} we skip the +% stroke part. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_fill_cmyk:n #1 + { \@@_backend_fill:n { cmyk ~ #1 } } +\cs_new_protected:Npn \@@_backend_fill_gray:n #1 + { \@@_backend_fill:n { gray ~ #1 } } +\cs_new_protected:Npn \@@_backend_fill_rgb:n #1 + { \@@_backend_fill:n { rgb ~ #1 } } +\cs_new_protected:Npn \@@_backend_fill:n #1 + { + \__kernel_backend_literal:n { color~push~ #1 } + } +\cs_new_protected:Npn \@@_backend_stroke_cmyk:n #1 + { \__kernel_backend_postscript:n { /color.sc { #1 ~ setcmykcolor } def } } +\cs_new_protected:Npn \@@_backend_stroke_gray:n #1 + { \__kernel_backend_postscript:n { /color.sc { #1 ~ setgray } def } } +\cs_new_protected:Npn \@@_backend_stroke_rgb:n #1 + { \__kernel_backend_postscript:n { /color.sc { #1 ~ setrgbcolor } def } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_fill_separation:nn, +% \@@_backend_stroke_separation:nn, +% \@@_backend_fill_devicen:nn, +% \@@_backend_stroke_devicen:nn +% } +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_fill_separation:nn #1#2 + { \@@_backend_fill:n { separation ~ #1 ~ #2 } } +\cs_new_protected:Npn \@@_backend_stroke_separation:nn #1#2 + { \__kernel_backend_postscript:n { /color.sc { separation ~ #1 ~ #2 } def } } +\cs_new_eq:NN \@@_backend_fill_devicen:nn \@@_backend_fill_separation:nn +\cs_new_eq:NN \@@_backend_stroke_devicen:nn \@@_backend_stroke_separation:nn +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_fill_reset:, \@@_backend_stroke_reset:} +% \begin{macrocode} +\cs_new_eq:NN \@@_backend_fill_reset: \@@_backend_reset: +\cs_new_protected:Npn \@@_backend_stroke_reset: { } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dvisvgm> +% \end{macrocode} +% +% \begin{macro} +% { +% \@@_backend_fill_cmyk:n , +% \@@_backend_fill_gray:n , +% \@@_backend_fill_rgb:n , +% \@@_backend_fill:n +% } +% Fill color here is the same as general color \emph{except} we skip the +% stroke part. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_fill_cmyk:n #1 + { \@@_backend_fill:n { cmyk ~ #1 } } +\cs_new_protected:Npn \@@_backend_fill_gray:n #1 + { \@@_backend_fill:n { gray ~ #1 } } +\cs_new_protected:Npn \@@_backend_fill_rgb:n #1 + { \@@_backend_fill:n { rgb ~ #1 } } +\cs_new_protected:Npn \@@_backend_fill:n #1 + { + \__kernel_backend_literal:n { color~push~ #1 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_stroke_cmyk:n} +% \begin{macro}{\@@_backend_stroke_cmyk:w} +% \begin{macro}{\@@_backend_stroke_gray:n, \@@_backend_stroke_gray_aux:n} +% \begin{macro}{\@@_backend_stroke_rgb:n} +% \begin{macro}{\@@_backend_stroke_rgb:w} +% \begin{macro}{\@@_backend:nnn} +% For drawings in SVG, we use scopes for all stroke colors. That +% requires using \texttt{RGB} values, which luckily are easy to +% convert here (|cmyk| to |RGB| is a fixed function). +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_stroke_cmyk:n #1 + { \@@_backend_cmyk:w #1 \s_@@_stop } +\cs_new_protected:Npn \@@_backend_stroke_cmyk:w + #1 ~ #2 ~ #3 ~ #4 \s_@@_stop + { + \use:e + { + \@@_backend:nnn + { \fp_eval:n { -100 * ( 1 - min ( 1 , #1 + #4 ) ) } } + { \fp_eval:n { -100 * ( 1 - min ( 1 , #2 + #4 ) ) } } + { \fp_eval:n { -100 * ( 1 - min ( 1 , #3 + #4 ) ) } } + } + } +\cs_new_protected:Npn \@@_backend_stroke_gray:n #1 + { + \use:e + { + \@@_backend_stroke_gray_aux:n + { \fp_eval:n { 100 * (#1) } } + } + } +\cs_new_protected:Npn \@@_backend_stroke_gray_aux:n #1 + { \@@_backend:nnn {#1} {#1} {#1} } +\cs_new_protected:Npn \@@_backend_stroke_rgb:n #1 + { \@@_backend_rgb:w #1 \s_@@_stop } +\cs_new_protected:Npn \@@_backend_stroke_rgb:w + #1 ~ #2 ~ #3 \s_@@_stop + { + \use:e + { + \@@_backend:nnn + { \fp_eval:n { 100 * (#1) } } + { \fp_eval:n { 100 * (#2) } } + { \fp_eval:n { 100 * (#3) } } + } + } +\cs_new_protected:Npe \@@_backend:nnn #1#2#3 + { + \__kernel_backend_scope:n + { + stroke = + " + rgb + ( + #1 \c_percent_str , + #2 \c_percent_str , + #3 \c_percent_str + ) + " + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_fill_separation:nn, +% \@@_backend_stroke_separation:nn, +% \@@_backend_fill_devicen:nn, +% \@@_backend_stroke_devicen:nn +% } +% At present, these are no-ops. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_fill_separation:nn #1#2 { } +\cs_new_protected:Npn \@@_backend_stroke_separation:nn #1#2 { } +\cs_new_eq:NN \@@_backend_fill_devicen:nn \@@_backend_fill_separation:nn +\cs_new_eq:NN \@@_backend_stroke_devicen:nn \@@_backend_stroke_separation:nn +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_fill_reset:, \@@_backend_stroke_reset:} +% \begin{macrocode} +\cs_new_eq:NN \@@_backend_fill_reset: \@@_backend_reset: +\cs_new_protected:Npn \@@_backend_stroke_reset: { } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_devicen_init:nnn, \@@_backend_iccbased_init:nnn} +% No support at present. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_devicen_init:nnn #1#2#3 { } +\cs_new_protected:Npn \@@_backend_iccbased_init:nnn #1#2#3 { } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{Font handling integration} +% +% In \LuaTeX{} these colors should also be usable to color fonts, so +% \texttt{luaotfload} color handling is extended to include these. +% +% \begin{macrocode} +%<*lua> +% \end{macrocode} +% +% \begin{macrocode} +local l = lpeg +local spaces = l.P' '^0 +local digit16 = l.R('09', 'af', 'AF') + +local octet = digit16 * digit16 / function(s) + return string.format('%.3g ', tonumber(s, 16) / 255) +end + +if luaotfload and luaotfload.set_transparent_colorstack then + local htmlcolor = l.Cs(octet * octet * octet * -1 * l.Cc'rg') + local color_export = { + token.create'tex_endlocalcontrol:D', + token.create'tex_hpack:D', + token.new(0, 1), + token.create'color_export:nnN', + token.new(0, 1), + '', + token.new(0, 2), + token.new(0, 1), + 'backend', + token.new(0, 2), + token.create'l_tmpa_tl', + token.create'exp_after:wN', + token.create'@@_select:nn', + token.create'l_tmpa_tl', + token.new(0, 2), + } + local group_end = token.create'group_end:' + local value = (1 - l.P'}')^0 + luatexbase.add_to_callback('luaotfload.parse_color', function (value) +% Also allow HTML colors to preserve compatibility + local html = htmlcolor:match(value) + if html then return html end + +% If no l3color named color with this name is known, check for defined xcolor colors + local l3color_prop = token.get_macro(string.format('l_@@_named_%s_prop', value)) + if l3color_prop == nil or l3color_prop == '' then + local legacy_color_macro = token.create(string.format('\\color@%s', value)) + if legacy_color_macro.cmdname ~= 'undefined_cs' then + token.put_next(legacy_color_macro) + return token.scan_argument() + end + end + + tex.runtoks(function() + token.get_next() + color_export[6] = value + tex.sprint(-2, color_export) + end) + local list = token.scan_list() + if not list.head or list.head.next + or list.head.subtype ~= node.subtype'pdf_colorstack' then + error'Unexpected backend behavior' + end + local cmd = list.head.data + node.free(list) + return cmd + end, 'l3color') +end +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*luatex> +% \end{macrocode} +% +% \begin{macrocode} +%<*package> +\lua_load_module:n {l3backend-luatex} +% +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex-dev/l3backend/l3backend-draw.dtx b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-draw.dtx new file mode 100644 index 00000000000..c651ab92fed --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-draw.dtx @@ -0,0 +1,1067 @@ +% \iffalse meta-comment +% +%% File: l3backend-draw.dtx +% +% Copyright (C) 2019-2024 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} +% +% \fi +% +% \title{^^A +% The \pkg{l3backend-draw} package\\ Backend drawing support^^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 2024-04-11} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3backend-draw} implementation} +% +% \begin{macrocode} +%<*package> +%<@@=draw> +% \end{macrocode} +% +% \subsection{\texttt{dvips} backend} +% +% \begin{macrocode} +%<*dvips> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_literal:n, \@@_backend_literal:e} +% The same as literal PostScript: same arguments about positioning apply +% here. +% \begin{macrocode} +\cs_new_eq:NN \@@_backend_literal:n \__kernel_backend_literal_postscript:n +\cs_generate_variant:Nn \@@_backend_literal:n { e } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_begin:, \@@_backend_end:} +% The |ps::[begin]| special here deals with positioning but allows us to +% continue on to a matching |ps::[end]|: contrast with |ps:|, which positions +% but where we can't split material between separate calls. The +% |@beginspecial|/|@endspecial| pair are from |special.pro| and correct the +% scale and $y$-axis direction. +% As for \pkg{pgf}, we need to save the current point as this is +% required for box placement. (Note that +% |@beginspecial|/|@endspecial| forms a backend scope.) +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_begin: + { + \@@_backend_literal:n { [begin] } + \@@_backend_literal:n { /draw.x~currentpoint~/draw.y~exch~def~def } + \@@_backend_literal:n { @beginspecial } + } +\cs_new_protected:Npn \@@_backend_end: + { + \@@_backend_literal:n { @endspecial } + \@@_backend_literal:n { [end] } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_scope_begin:, \@@_backend_scope_end:} +% Scope here may need to contain saved definitions, so the entire memory +% rather than just the graphic state has to be sent to the stack. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_scope_begin: + { \@@_backend_literal:n { save } } +\cs_new_protected:Npn \@@_backend_scope_end: + { \@@_backend_literal:n { restore } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_moveto:nn, \@@_backend_lineto:nn} +% \begin{macro}{\@@_backend_rectangle:nnnn} +% \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 +% 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. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_moveto:nn #1#2 + { + \@@_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ + \dim_to_decimal_in_bp:n {#2} ~ moveto + } + } +\cs_new_protected:Npn \@@_backend_lineto:nn #1#2 + { + \@@_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ + \dim_to_decimal_in_bp:n {#2} ~ lineto + } + } +\cs_new_protected:Npn \@@_backend_rectangle:nnnn #1#2#3#4 + { + \@@_backend_literal:e + { + \dim_to_decimal_in_bp:n {#4} ~ \dim_to_decimal_in_bp:n {#3} ~ + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + moveto~dup~0~rlineto~exch~0~exch~rlineto~neg~0~rlineto~closepath + } + } +\cs_new_protected:Npn \@@_backend_curveto:nnnnnn #1#2#3#4#5#6 + { + \@@_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~ + curveto + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_evenodd_rule:, \@@_backend_nonzero_rule:} +% \begin{variable}{\g_@@_draw_eor_bool} +% The even-odd rule here can be implemented as a simply switch. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_evenodd_rule: + { \bool_gset_true:N \g_@@_draw_eor_bool } +\cs_new_protected:Npn \@@_backend_nonzero_rule: + { \bool_gset_false:N \g_@@_draw_eor_bool } +\bool_new:N \g_@@_draw_eor_bool +% \end{macrocode} +% \end{variable} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_closepath: , +% \@@_backend_stroke: , +% \@@_backend_closestroke: , +% \@@_backend_fill: , +% \@@_backend_fillstroke: , +% \@@_backend_clip: , +% \@@_backend_discardpath: +% } +% \begin{variable}{\g_@@_draw_clip_bool} +% Unlike PDF, PostScript doesn't track separate colors for strokes and other +% elements. It is also desirable to have the |clip| keyword after a stroke or +% fill. To achieve those outcomes, there is some work to do. For color, the +% stoke color is simple but the fill one has to be inserted by hand. For +% clipping, the required ordering is achieved using a \TeX{} switch. All of +% the operations end with a new path instruction as they do not terminate +% (again in contrast to PDF). +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_closepath: + { \@@_backend_literal:n { closepath } } +\cs_new_protected:Npn \@@_backend_stroke: + { + \@@_backend_literal:n { gsave } + \@@_backend_literal:n { color.sc } + \@@_backend_literal:n { stroke } + \@@_backend_literal:n { grestore } + \bool_if:NT \g_@@_draw_clip_bool + { + \@@_backend_literal:e + { + \bool_if:NT \g_@@_draw_eor_bool { eo } + clip + } + } + \@@_backend_literal:n { newpath } + \bool_gset_false:N \g_@@_draw_clip_bool + } +\cs_new_protected:Npn \@@_backend_closestroke: + { + \@@_backend_closepath: + \@@_backend_stroke: + } +\cs_new_protected:Npn \@@_backend_fill: + { + \@@_backend_literal:e + { + \bool_if:NT \g_@@_draw_eor_bool { eo } + fill + } + \bool_if:NT \g_@@_draw_clip_bool + { + \@@_backend_literal:e + { + \bool_if:NT \g_@@_draw_eor_bool { eo } + clip + } + } + \@@_backend_literal:n { newpath } + \bool_gset_false:N \g_@@_draw_clip_bool + } +\cs_new_protected:Npn \@@_backend_fillstroke: + { + \@@_backend_literal:e + { + \bool_if:NT \g_@@_draw_eor_bool { eo } + fill + } + \@@_backend_literal:n { gsave } + \@@_backend_literal:n { color.sc } + \@@_backend_literal:n { stroke } + \@@_backend_literal:n { grestore } + \bool_if:NT \g_@@_draw_clip_bool + { + \@@_backend_literal:e + { + \bool_if:NT \g_@@_draw_eor_bool { eo } + clip + } + } + \@@_backend_literal:n { newpath } + \bool_gset_false:N \g_@@_draw_clip_bool + } +\cs_new_protected:Npn \@@_backend_clip: + { \bool_gset_true:N \g_@@_draw_clip_bool } +\bool_new:N \g_@@_draw_clip_bool +\cs_new_protected:Npn \@@_backend_discardpath: + { + \bool_if:NT \g_@@_draw_clip_bool + { + \@@_backend_literal:e + { + \bool_if:NT \g_@@_draw_eor_bool { eo } + clip + } + } + \@@_backend_literal:n { newpath } + \bool_gset_false:N \g_@@_draw_clip_bool + } +% \end{macrocode} +% \end{variable} +% \end{macro} +% +% \begin{macro}{\@@_backend_dash_pattern:nn} +% \begin{macro}{\@@_backend_dash:n} +% \begin{macro}{\@@_backend_linewidth:n} +% \begin{macro}{\@@_backend_miterlimit:n} +% \begin{macro} +% { +% \@@_backend_cap_butt:, \@@_backend_cap_round:, \@@_backend_cap_rectangle:, +% \@@_backend_join_miter:, \@@_backend_join_round:, \@@_backend_join_bevel: +% } +% Converting paths to output is again a case of mapping directly to +% PostScript operations. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_dash_pattern:nn #1#2 + { + \@@_backend_literal:e + { + [ + \exp_args:Nf \use:n + { \clist_map_function:nN {#1} \@@_backend_dash:n } + ] ~ + \dim_to_decimal_in_bp:n {#2} ~ setdash + } + } +\cs_new:Npn \@@_backend_dash:n #1 + { ~ \dim_to_decimal_in_bp:n {#1} } +\cs_new_protected:Npn \@@_backend_linewidth:n #1 + { + \@@_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ setlinewidth } + } +\cs_new_protected:Npn \@@_backend_miterlimit:n #1 + { \@@_backend_literal:n { #1 ~ setmiterlimit } } +\cs_new_protected:Npn \@@_backend_cap_butt: + { \@@_backend_literal:n { 0 ~ setlinecap } } +\cs_new_protected:Npn \@@_backend_cap_round: + { \@@_backend_literal:n { 1 ~ setlinecap } } +\cs_new_protected:Npn \@@_backend_cap_rectangle: + { \@@_backend_literal:n { 2 ~ setlinecap } } +\cs_new_protected:Npn \@@_backend_join_miter: + { \@@_backend_literal:n { 0 ~ setlinejoin } } +\cs_new_protected:Npn \@@_backend_join_round: + { \@@_backend_literal:n { 1 ~ setlinejoin } } +\cs_new_protected:Npn \@@_backend_join_bevel: + { \@@_backend_literal:n { 2 ~ setlinejoin } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\@@_backend_cm:nnnn} +% 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 +% 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 + { + \@@_backend_literal:n + { [ #1 ~ #2 ~ #3 ~ #4 ~ 0 ~ 0 ] ~ concat } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_box_use:Nnnnn} +% Inside a picture |@beginspecial|/|@endspecial| are active, which is +% normally a good thing but means that the position and scaling would be off +% if the box was inserted directly. To deal with that, there are a number of +% possible approaches. A previous implementation suggested by Tom Rokici +% used |@endspecial|/|@beginspecial|. This avoids needing internals of +% \texttt{dvips}, but fails if there the box is used inside a scope +% (see \url{https://github.com/latex3/latex3/issues/1504}). Instead, +% we use the same method as \pkg{pgf}, which means tracking the position +% at the PostScript level. Also note that using |@endspecial| would +% close the scope it creates, meaning that after a box insertion, any +% local changes would be lost. Keeping \texttt{dvips} on track is +% non-trivial, hence the |[begin]|/|[end]| pair before the +% |save| and around the |restore|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_box_use:Nnnnn #1#2#3#4#5 + { + \@@_backend_literal:n { save } + \@@_backend_literal:n { 72~Resolution~div~72~VResolution~div~neg~scale } + \@@_backend_literal:n { magscale { 1~DVImag~div~dup~scale } if } + \@@_backend_literal:n { draw.x~neg~draw.y~neg~translate } + \@@_backend_literal:n { [end] } + \@@_backend_literal:n { [begin] } + \@@_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_literal:n { neg~exch~neg~exch~translate } + \@@_backend_literal:n { [end] } + \hbox_overlap_right:n { \box_use:N #1 } + \@@_backend_literal:n { [begin] } + \@@_backend_literal:n { restore } + \@@_backend_literal:n { [end] } + \@@_backend_literal:n { [begin] } + \@@_backend_literal:n { restore } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\LuaTeX{}, \pdfTeX{}, \texttt{dvipdfmx} and \XeTeX{}} +% +% \LuaTeX{}, \pdfTeX{}, \texttt{dvipdfmx} and \XeTeX{} directly produce PDF output +% and understand a shared set of specials for drawing commands. +% +% \begin{macrocode} +%<*dvipdfmx|luatex|pdftex|xetex> +% \end{macrocode} +% +% \subsubsection{Drawing} +% +% \begin{macro}{\@@_backend_literal:n, \@@_backend_literal:e} +% 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 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_begin:, \@@_backend_end:} +% No special requirements here, so simply set up a drawing scope. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_begin: + { \@@_backend_scope_begin: } +\cs_new_protected:Npn \@@_backend_end: + { \@@_backend_scope_end: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_scope_begin:, \@@_backend_scope_end:} +% Use the backend-level scope mechanisms. +% \begin{macrocode} +\cs_new_eq:NN \@@_backend_scope_begin: \__kernel_backend_scope_begin: +\cs_new_eq:NN \@@_backend_scope_end: \__kernel_backend_scope_end: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_moveto:nn, \@@_backend_lineto:nn} +% \begin{macro}{\@@_backend_curveto:nnnnnn} +% \begin{macro}{\@@_backend_rectangle:nnnn} +% Path creation operations all resolve directly to PDF primitive steps, with +% only the need to convert to \texttt{bp}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_moveto:nn #1#2 + { + \@@_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ m } + } +\cs_new_protected:Npn \@@_backend_lineto:nn #1#2 + { + \@@_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ l } + } +\cs_new_protected:Npn \@@_backend_curveto:nnnnnn #1#2#3#4#5#6 + { + \@@_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~ + c + } + } +\cs_new_protected:Npn \@@_backend_rectangle:nnnn #1#2#3#4 + { + \@@_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + re + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_evenodd_rule:, \@@_backend_nonzero_rule:} +% \begin{variable}{\g_@@_draw_eor_bool} +% The even-odd rule here can be implemented as a simply switch. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_evenodd_rule: + { \bool_gset_true:N \g_@@_draw_eor_bool } +\cs_new_protected:Npn \@@_backend_nonzero_rule: + { \bool_gset_false:N \g_@@_draw_eor_bool } +\bool_new:N \g_@@_draw_eor_bool +% \end{macrocode} +% \end{variable} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_closepath: , +% \@@_backend_stroke: , +% \@@_backend_closestroke: , +% \@@_backend_fill: , +% \@@_backend_fillstroke: , +% \@@_backend_clip: , +% \@@_backend_discardpath: +% } +% Converting paths to output is again a case of mapping directly to +% PDF operations. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_closepath: + { \@@_backend_literal:n { h } } +\cs_new_protected:Npn \@@_backend_stroke: + { \@@_backend_literal:n { S } } +\cs_new_protected:Npn \@@_backend_closestroke: + { \@@_backend_literal:n { s } } +\cs_new_protected:Npn \@@_backend_fill: + { + \@@_backend_literal:e + { f \bool_if:NT \g_@@_draw_eor_bool * } + } +\cs_new_protected:Npn \@@_backend_fillstroke: + { + \@@_backend_literal:e + { B \bool_if:NT \g_@@_draw_eor_bool * } + } +\cs_new_protected:Npn \@@_backend_clip: + { + \@@_backend_literal:e + { W \bool_if:NT \g_@@_draw_eor_bool * } + } +\cs_new_protected:Npn \@@_backend_discardpath: + { \@@_backend_literal:n { n } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_dash_pattern:nn} +% \begin{macro}{\@@_backend_dash:n} +% \begin{macro}{\@@_backend_linewidth:n} +% \begin{macro}{\@@_backend_miterlimit:n} +% \begin{macro} +% { +% \@@_backend_cap_butt:, \@@_backend_cap_round:, \@@_backend_cap_rectangle:, +% \@@_backend_join_miter:, \@@_backend_join_round:, \@@_backend_join_bevel: +% } +% Converting paths to output is again a case of mapping directly to +% PDF operations. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_dash_pattern:nn #1#2 + { + \@@_backend_literal:e + { + [ + \exp_args:Nf \use:n + { \clist_map_function:nN {#1} \@@_backend_dash:n } + ] ~ + \dim_to_decimal_in_bp:n {#2} ~ d + } + } +\cs_new:Npn \@@_backend_dash:n #1 + { ~ \dim_to_decimal_in_bp:n {#1} } +\cs_new_protected:Npn \@@_backend_linewidth:n #1 + { + \@@_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ w } + } +\cs_new_protected:Npn \@@_backend_miterlimit:n #1 + { \@@_backend_literal:e { #1 ~ M } } +\cs_new_protected:Npn \@@_backend_cap_butt: + { \@@_backend_literal:n { 0 ~ J } } +\cs_new_protected:Npn \@@_backend_cap_round: + { \@@_backend_literal:n { 1 ~ J } } +\cs_new_protected:Npn \@@_backend_cap_rectangle: + { \@@_backend_literal:n { 2 ~ J } } +\cs_new_protected:Npn \@@_backend_join_miter: + { \@@_backend_literal:n { 0 ~ j } } +\cs_new_protected:Npn \@@_backend_join_round: + { \@@_backend_literal:n { 1 ~ j } } +\cs_new_protected:Npn \@@_backend_join_bevel: + { \@@_backend_literal:n { 2 ~ j } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_cm:nnnn} +% \begin{macro}{\@@_backend_cm_aux:nnnn} +% 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 +% matrix into rotations and a scaling, then use those operations as they +% are handled by the backend. (There is backend support for matrix operations in +% \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! +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_cm:nnnn #1#2#3#4 + { +%<*luatex|pdftex> + \__kernel_backend_matrix:n { #1 ~ #2 ~ #3 ~ #4 } +% +%<*dvipdfmx|xetex> + \@@_backend_cm_decompose:nnnnN {#1} {#2} {#3} {#4} + \@@_backend_cm_aux:nnnn +% + } +%<*dvipdfmx|xetex> +\cs_new_protected:Npn \@@_backend_cm_aux:nnnn #1#2#3#4 + { + \__kernel_backend_literal:e + { + x:rotate~ + \fp_compare:nNnTF {#1} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( -#1 , 5 ) } } + } + \__kernel_backend_literal:e + { + x:scale~ + \fp_eval:n { round ( #2 , 5 ) } ~ + \fp_eval:n { round ( #3 , 5 ) } + } + \__kernel_backend_literal:e + { + x:rotate~ + \fp_compare:nNnTF {#4} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( -#4 , 5 ) } } + } + } +% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_cm_decompose:nnnnN} +% \begin{macro} +% { +% \@@_backend_cm_decompose_auxi:nnnnN, +% \@@_backend_cm_decompose_auxii:nnnnN, +% \@@_backend_cm_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 +% engine looses track of positions (for example for hyperlinks), and this is +% not desirable. They do, however, allow us to track rotations and scalings. +% Luckily, we can decompose any (two-dimensional) matrix into two rotations +% and a single scaling: +% \[ +% \begin{bmatrix} +% A & B \\ C & D +% \end{bmatrix} +% = +% \begin{bmatrix} +% \cos\beta & \sin\beta \\ -\sin\beta & \cos\beta +% \end{bmatrix} +% \begin{bmatrix} +% w_{1} & 0 \\ 0 & w_{2} +% \end{bmatrix} +% \begin{bmatrix} +% \cos\gamma & \sin\gamma \\ -\sin\gamma & \cos\gamma +% \end{bmatrix} +% \] +% The parent matrix can be converted to +% \[ +% \begin{bmatrix} +% A & B \\ C & D +% \end{bmatrix} +% = +% \begin{bmatrix} +% E & H \\-H & E +% \end{bmatrix} +% + +% \begin{bmatrix} +% F & G \\ G & -F +% \end{bmatrix} +% \] +% From these, we can find that +% \begin{align*} +% \frac{w_{1} + w_{2}}{2} &= \sqrt{E^{2} + H^{2}} \\ +% \frac{w_{1} - w_{2}}{2} &= \sqrt{F^{2} + G^{2}} \\ +% \gamma - \beta &= \tan^{-1}(G/F) \\ +% \gamma + \beta &= \tan^{-1}(H/E) +% \end{align*} +% at which point we just have to do various pieces of re-arrangement to +% get all of the values. (See J.~Blinn, \emph{IEEE Comput.\ Graph.\ Appl.}, +% 1996, \textbf{16}, 82--88.) There is one wrinkle: the PostScript (and PDF) +% way of specifying a transformation matrix exchanges where one would +% normally expect $B$ and $C$ to be. +% \begin{macrocode} +%<*dvipdfmx|xetex> +\cs_new_protected:Npn \@@_backend_cm_decompose:nnnnN #1#2#3#4#5 + { + \use:e + { + \@@_backend_cm_decompose_auxi:nnnnN + { \fp_eval:n { (#1 + #4) / 2 } } + { \fp_eval:n { (#1 - #4) / 2 } } + { \fp_eval:n { (#3 + #2) / 2 } } + { \fp_eval:n { (#3 - #2) / 2 } } + } + #5 + } +\cs_new_protected:Npn \@@_backend_cm_decompose_auxi:nnnnN #1#2#3#4#5 + { + \use:e + { + \@@_backend_cm_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 ) } } + { \fp_eval:n { atand ( #4 , #1 ) } } + } + #5 + } +\cs_new_protected:Npn \@@_backend_cm_decompose_auxii:nnnnN #1#2#3#4#5 + { + \use:e + { + \@@_backend_cm_decompose_auxiii:nnnnN + { \fp_eval:n { ( #4 - #3 ) / 2 } } + { \fp_eval:n { ( #1 + #2 ) / 2 } } + { \fp_eval:n { ( #1 - #2 ) / 2 } } + { \fp_eval:n { ( #4 + #3 ) / 2 } } + } + #5 + } +\cs_new_protected:Npn \@@_backend_cm_decompose_auxiii:nnnnN #1#2#3#4#5 + { + \fp_compare:nNnTF { abs( #2 ) } > { abs ( #3 ) } + { #5 {#1} {#2} {#3} {#4} } + { #5 {#1} {#3} {#2} {#4} } + } +% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_box_use:Nnnnn} +% Inserting a \TeX{} box transformed to the requested position and using +% the current matrix is done using a mixture of \TeX{} and low-level +% manipulation. The offset can be handled by \TeX{}, so only any rotation/^^A +% skew/scaling component needs to be done using the matrix operation. As this +% operation can never be cached, the scope is set directly not using the +% \texttt{draw} version. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_box_use:Nnnnn #1#2#3#4#5 + { + \__kernel_backend_scope_begin: +%<*luatex|pdftex> + \@@_backend_cm:nnnn {#2} {#3} {#4} {#5} +% +%<*dvipdfmx|xetex> + \__kernel_backend_literal:n + { pdf:btrans~matrix~ #2 ~ #3 ~ #4 ~ #5 ~ 0 ~ 0 } +% + \hbox_overlap_right:n { \box_use:N #1 } +%<*dvipdfmx|xetex> + \__kernel_backend_literal:n { pdf:etrans } +% + \__kernel_backend_scope_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\texttt{dvisvgm} backend} +% +% \begin{macrocode} +%<*dvisvgm> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_literal:n, \@@_backend_literal:e} +% The same as the more general literal call. +% \begin{macrocode} +\cs_new_eq:NN \@@_backend_literal:n \__kernel_backend_literal_svg:n +\cs_generate_variant:Nn \@@_backend_literal:n { e } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_scope_begin:, \@@_backend_scope_end:} +% Use the backend-level scope mechanisms. +% \begin{macrocode} +\cs_new_eq:NN \@@_backend_scope_begin: \__kernel_backend_scope_begin: +\cs_new_eq:NN \@@_backend_scope_end: \__kernel_backend_scope_end: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_begin:, \@@_backend_end:} +% A drawing needs to be set up such that the co-ordinate system is +% translated. That is done inside a scope, which as described below +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_begin: + { + \__kernel_backend_scope_begin: + \__kernel_backend_scope:n { transform="translate({?x},{?y})~scale(1,-1)" } + } +\cs_new_eq:NN \@@_backend_end: \__kernel_backend_scope_end: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_moveto:nn, \@@_backend_lineto:nn} +% \begin{macro}{\@@_backend_rectangle:nnnn} +% \begin{macro}{\@@_backend_curveto:nnnnnn} +% \begin{macro}{\@@_backend_add_to_path:n} +% \begin{variable}{\g_@@_backend_path_tl} +% Once again, some work is needed to get path constructs correct. Rather +% then write the values as they are given, the entire path needs to be +% 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. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_moveto:nn #1#2 + { + \@@_backend_add_to_path:n + { M ~ \dim_to_decimal:n {#1} ~ \dim_to_decimal:n {#2} } + } +\cs_new_protected:Npn \@@_backend_lineto:nn #1#2 + { + \@@_backend_add_to_path:n + { L ~ \dim_to_decimal:n {#1} ~ \dim_to_decimal:n {#2} } + } +\cs_new_protected:Npn \@@_backend_rectangle:nnnn #1#2#3#4 + { + \@@_backend_add_to_path:n + { + M ~ \dim_to_decimal:n {#1} ~ \dim_to_decimal:n {#2} + h ~ \dim_to_decimal:n {#3} ~ + v ~ \dim_to_decimal:n {#4} ~ + h ~ \dim_to_decimal:n { -#3 } ~ + Z + } + } +\cs_new_protected:Npn \@@_backend_curveto:nnnnnn #1#2#3#4#5#6 + { + \@@_backend_add_to_path:n + { + C ~ + \dim_to_decimal:n {#1} ~ \dim_to_decimal:n {#2} ~ + \dim_to_decimal:n {#3} ~ \dim_to_decimal:n {#4} ~ + \dim_to_decimal:n {#5} ~ \dim_to_decimal:n {#6} + } + } +\cs_new_protected:Npn \@@_backend_add_to_path:n #1 + { + \tl_gset:Ne \g_@@_backend_path_tl + { + \g_@@_backend_path_tl + \tl_if_empty:NF \g_@@_backend_path_tl { \c_space_tl } + #1 + } + } +\tl_new:N \g_@@_backend_path_tl +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_evenodd_rule:, \@@_backend_nonzero_rule:} +% The fill rules here have to be handled as scopes. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_evenodd_rule: + { \__kernel_backend_scope:n { fill-rule="evenodd" } } +\cs_new_protected:Npn \@@_backend_nonzero_rule: + { \__kernel_backend_scope:n { fill-rule="nonzero" } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_path:n} +% \begin{macro} +% { +% \@@_backend_closepath: , +% \@@_backend_stroke: , +% \@@_backend_closestroke: , +% \@@_backend_fill: , +% \@@_backend_fillstroke: , +% \@@_backend_clip: , +% \@@_backend_discardpath: +% } +% \begin{variable}{\g_@@_draw_clip_bool} +% \begin{variable}{\g_@@_draw_path_int} +% Setting fill and stroke effects and doing clipping all has to be done using +% scopes. This means setting up the various requirements in a shared +% auxiliary which deals with the bits and pieces. Clipping paths are reused +% for path drawing: not essential but avoids constructing them twice. +% Discarding a path needs a separate function as it's not quite the same. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_closepath: + { \@@_backend_add_to_path:n { Z } } +\cs_new_protected:Npn \@@_backend_path:n #1 + { + \bool_if:NTF \g_@@_draw_clip_bool + { + \int_gincr:N \g__kernel_clip_path_int + \@@_backend_literal:e + { + < clipPath~id = " l3cp \int_use:N \g__kernel_clip_path_int " > + { ?nl } + { ?nl } + < /clipPath > { ? nl } + < + use~xlink:href = + "\c_hash_str l3path \int_use:N \g_@@_backend_path_int " ~ + #1 + /> + } + \__kernel_backend_scope:e + { + clip-path = + "url( \c_hash_str l3cp \int_use:N \g__kernel_clip_path_int)" + } + } + { + \@@_backend_literal:e + { } + } + \tl_gclear:N \g_@@_backend_path_tl + \bool_gset_false:N \g_@@_draw_clip_bool + } +\int_new:N \g_@@_backend_path_int +\cs_new_protected:Npn \@@_backend_stroke: + { \@@_backend_path:n { style="fill:none" } } +\cs_new_protected:Npn \@@_backend_closestroke: + { + \@@_backend_closepath: + \@@_backend_stroke: + } +\cs_new_protected:Npn \@@_backend_fill: + { \@@_backend_path:n { style="stroke:none" } } +\cs_new_protected:Npn \@@_backend_fillstroke: + { \@@_backend_path:n { } } +\cs_new_protected:Npn \@@_backend_clip: + { \bool_gset_true:N \g_@@_draw_clip_bool } +\bool_new:N \g_@@_draw_clip_bool +\cs_new_protected:Npn \@@_backend_discardpath: + { + \bool_if:NT \g_@@_draw_clip_bool + { + \int_gincr:N \g__kernel_clip_path_int + \@@_backend_literal:e + { + < clipPath~id = " l3cp \int_use:N \g__kernel_clip_path_int " > + { ?nl } + { ?nl } + < /clipPath > + } + \__kernel_backend_scope:e + { + clip-path = + "url( \c_hash_str l3cp \int_use:N \g__kernel_clip_path_int)" + } + } + \tl_gclear:N \g_@@_backend_path_tl + \bool_gset_false:N \g_@@_draw_clip_bool + } +% \end{macrocode} +% \end{variable} +% \end{variable} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_dash_pattern:nn} +% \begin{macro}{\@@_backend_dash:n} +% \begin{macro}{\@@_backend_dash_aux:nn} +% \begin{macro}{\@@_backend_linewidth:n} +% \begin{macro}{\@@_backend_miterlimit:n} +% \begin{macro} +% { +% \@@_backend_cap_butt:, \@@_backend_cap_round:, \@@_backend_cap_rectangle:, +% \@@_backend_join_miter:, \@@_backend_join_round:, \@@_backend_join_bevel: +% } +% All of these ideas are properties of scopes in SVG. The only slight +% complexity is converting the dash array properly (doing any required +% maths). +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_dash_pattern:nn #1#2 + { + \use:e + { + \@@_backend_dash_aux:nn + { \clist_map_function:nN {#1} \@@_backend_dash:n } + { \dim_to_decimal:n {#2} } + } + } +\cs_new:Npn \@@_backend_dash:n #1 + { , \dim_to_decimal_in_bp:n {#1} } +\cs_new_protected:Npn \@@_backend_dash_aux:nn #1#2 + { + \__kernel_backend_scope:e + { + stroke-dasharray = + " + \tl_if_empty:nTF {#1} + { none } + { \use_none:n #1 } + " ~ + stroke-offset=" #2 " + } + } +\cs_new_protected:Npn \@@_backend_linewidth:n #1 + { \__kernel_backend_scope:e { stroke-width=" \dim_to_decimal:n {#1} " } } +\cs_new_protected:Npn \@@_backend_miterlimit:n #1 + { \__kernel_backend_scope:e { stroke-miterlimit=" #1 " } } +\cs_new_protected:Npn \@@_backend_cap_butt: + { \__kernel_backend_scope:n { stroke-linecap="butt" } } +\cs_new_protected:Npn \@@_backend_cap_round: + { \__kernel_backend_scope:n { stroke-linecap="round" } } +\cs_new_protected:Npn \@@_backend_cap_rectangle: + { \__kernel_backend_scope:n { stroke-linecap="square" } } +\cs_new_protected:Npn \@@_backend_join_miter: + { \__kernel_backend_scope:n { stroke-linejoin="miter" } } +\cs_new_protected:Npn \@@_backend_join_round: + { \__kernel_backend_scope:n { stroke-linejoin="round" } } +\cs_new_protected:Npn \@@_backend_join_bevel: + { \__kernel_backend_scope:n { stroke-linejoin="bevel" } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_cm:nnnn} +% 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 + { + \__kernel_backend_scope:n + { + transform = + " matrix ( #1 , #2 , #3 , #4 , 0pt , 0pt ) " + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_box_use:Nnnnn} +% No special savings can be made here: simply displace the box inside +% a scope. As there is nothing to re-box, just make the box passed of +% zero size. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_box_use:Nnnnn #1#2#3#4#5 + { + \__kernel_backend_scope_begin: + \@@_backend_cm:nnnn {#2} {#3} {#4} {#5} + \__kernel_backend_literal_svg:n + { + < g~ + stroke="none"~ + transform="scale(-1,1)~translate({?x},{?y})~scale(-1,-1)" + > + } + \box_set_wd:Nn #1 { 0pt } + \box_set_ht:Nn #1 { 0pt } + \box_set_dp:Nn #1 { 0pt } + \box_use:N #1 + \__kernel_backend_literal_svg:n { } + \__kernel_backend_scope_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx new file mode 100644 index 00000000000..e20457368da --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-graphics.dtx @@ -0,0 +1,931 @@ +% \iffalse meta-comment +% +%% File: l3backend-graphics.dtx +% +% Copyright (C) 2019-2024 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} +% +% \fi +% +% \title{^^A +% The \pkg{l3backend-graphics} module\\ Backend graphics support^^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 2024-04-11} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3backend-graphics} implementation} +% +% \begin{macrocode} +%<*package> +%<@@=graphics> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_loaded:n} +% To deal with file load ordering. Plain users are on their own. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_loaded:n #1 + { + \cs_if_exist:NTF \hook_gput_code:nnn + { + \hook_gput_code:nnn + { package / l3graphics / after } + { backend } + {#1} + } + {#1} + } +% \end{macrocode} +% \end{macro} +% +% \subsection{\texttt{dvips} backend} +% +% \begin{macrocode} +%<*dvips> +% \end{macrocode} +% +% \begin{variable}[no-user-doc]{\l_graphics_search_ext_seq} +% \begin{macrocode} +\@@_backend_loaded:n + { \seq_set_from_clist:Nn \l_graphics_search_ext_seq { .eps , .ps } } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_backend_getbb_eps:n, \@@_backend_getbb_ps:n} +% Simply use the generic function. +% \begin{macrocode} +\@@_backend_loaded:n + { + \cs_new_eq:NN \@@_backend_getbb_eps:n \@@_read_bb:n + \cs_new_eq:NN \@@_backend_getbb_ps:n \@@_read_bb:n + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_include_eps:n, \@@_backend_include_ps:n} +% The special syntax is relatively clear here: remember we need PostScript +% sizes here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_include_eps:n #1 + { + \__kernel_backend_literal:e + { + PSfile = #1 \c_space_tl + llx = \dim_to_decimal_in_bp:n \l_@@_llx_dim \c_space_tl + lly = \dim_to_decimal_in_bp:n \l_@@_lly_dim \c_space_tl + urx = \dim_to_decimal_in_bp:n \l_@@_urx_dim \c_space_tl + ury = \dim_to_decimal_in_bp:n \l_@@_ury_dim + } + } +\cs_new_eq:NN \@@_backend_include_ps:n \@@_backend_include_eps:n +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_get_pagecount:n} +% \begin{macrocode} +\@@_backend_loaded:n + { \cs_new_eq:NN \@@_backend_get_pagecount:n \@@_get_pagecount:n } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\LuaTeX{} and \pdfTeX{} backends} +% +% \begin{macrocode} +%<*luatex|pdftex> +% \end{macrocode} +% +% \begin{variable}[no-user-doc]{\l_graphics_search_ext_seq} +% \begin{macrocode} +\@@_backend_loaded:n + { + \seq_set_from_clist:Nn + \l_graphics_search_ext_seq + { .pdf , .eps , .ps , .png , .jpg , .jpeg } + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_attr_tl} +% In PDF mode, additional attributes of an graphic (such as page number) are +% needed both to obtain the bounding box and when inserting the graphic: this +% occurs as the graphic dictionary approach means they are read as part of +% the bounding box operation. As such, it is easier to track additional +% attributes using a dedicated |tl| rather than build up the same data +% twice. +% \begin{macrocode} +\tl_new:N \l_@@_attr_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro} +% { +% \@@_backend_getbb_jpg:n , +% \@@_backend_getbb_jpeg:n , +% \@@_backend_getbb_pdf:n , +% \@@_backend_getbb_png:n +% } +% \begin{macro} +% { +% \@@_backend_getbb_auxi:n , +% \@@_backend_getbb_auxii:n , +% \@@_backend_getbb_auxiii:n +% } +% \begin{macro}[EXP]{\@@_backend_dequote:w} +% Getting the bounding box here requires us to box up the graphic and +% measure it. To deal with the difference in feature support in bitmap +% and vector graphics but keeping the common parts, there is a little work +% to do in terms of auxiliaries. The key here is to notice that we need +% two forms of the attributes: a \enquote{short} set to allow us to +% track for caching, and the full form to pass to the primitive. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_getbb_jpg:n #1 + { + \int_zero:N \l_@@_page_int + \tl_clear:N \l_@@_pagebox_tl + \tl_set:Ne \l_@@_attr_tl + { + \tl_if_empty:NF \l_@@_decodearray_str + { :D \l_@@_decodearray_str } + \bool_if:NT \l_@@_interpolate_bool + { :I } + \str_if_empty:NF \l_@@_pdf_str + { :X \l_@@_pdf_str } + } + \@@_backend_getbb_auxi:n {#1} + } +\cs_new_eq:NN \@@_backend_getbb_jpeg:n \@@_backend_getbb_jpg:n +\cs_new_eq:NN \@@_backend_getbb_png:n \@@_backend_getbb_jpg:n +\cs_new_protected:Npn \@@_backend_getbb_pdf:n #1 + { + \tl_clear:N \l_@@_decodearray_str + \bool_set_false:N \l_@@_interpolate_bool + \tl_set:Ne \l_@@_attr_tl + { + : \l_@@_pagebox_tl + \int_compare:nNnT \l_@@_page_int > 1 + { :P \int_use:N \l_@@_page_int } + \str_if_empty:NF \l_@@_pdf_str + { :X \l_@@_pdf_str } + } + \@@_backend_getbb_auxi:n {#1} + } +\cs_new_protected:Npn \@@_backend_getbb_auxi:n #1 + { + \@@_bb_restore:eF { #1 \l_@@_attr_tl } + { \@@_backend_getbb_auxii:n {#1} } + } +% \end{macrocode} +% Measuring the graphic is done by boxing up: for PDF graphics we could +% use |\tex_pdfximagebbox:D|, but if doesn't work for other types. +% As the box always starts at $(0,0)$ there is no need to worry about +% the lower-left position. Quotes need to be \emph{removed} as \LuaTeX{} +% does not like them here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_getbb_auxii:n #1 + { + \exp_args:Ne \@@_backend_getbb_auxiii:n + { \@@_backend_dequote:w #1 " #1 " \s_@@_stop } + \int_const:cn { c_@@_ #1 \l_@@_attr_tl _int } + { \tex_the:D \tex_pdflastximage:D } + \@@_bb_save:e { #1 \l_@@_attr_tl } + } +\cs_new_protected:Npn \@@_backend_getbb_auxiii:n #1 + { + \tex_immediate:D \tex_pdfximage:D + \bool_lazy_any:nT + { + { \l_@@_interpolate_bool } + { ! \tl_if_empty_p:N \l_@@_decodearray_str } + { ! \str_if_empty_p:N \l_@@_pdf_str } + } + { + attr ~ + { + \tl_if_empty:NF \l_@@_decodearray_str + { /Decode~[ \l_@@_decodearray_str ] } + \bool_if:NT \l_@@_interpolate_bool + { /Interpolate~true } + \l_@@_pdf_str + } + } + \int_compare:nNnT \l_@@_page_int > 0 + { page ~ \int_use:N \l_@@_page_int } + \tl_if_empty:NF \l_@@_pagebox_tl + { \l_@@_pagebox_tl } + {#1} + \hbox_set:Nn \l_@@_internal_box + { \tex_pdfrefximage:D \tex_pdflastximage:D } + \dim_set:Nn \l_@@_urx_dim { \box_wd:N \l_@@_internal_box } + \dim_set:Nn \l_@@_ury_dim { \box_ht:N \l_@@_internal_box } + } +\cs_new:Npn \@@_backend_dequote:w #1 " #2 " #3 \s_@@_stop {#2} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_include_jpg:n , +% \@@_backend_include_jpeg:n , +% \@@_backend_include_pdf:n , +% \@@_backend_include_png:n +% } +% Images are already loaded for the measurement part of the code, so +% inclusion is straight-forward, with only any attributes to worry about. The +% latter carry through from determination of the bounding box. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_include_jpg:n #1 + { + \tex_pdfrefximage:D + \int_use:c { c_@@_ #1 \l_@@_attr_tl _int } + } +\cs_new_eq:NN \@@_backend_include_jpeg:n \@@_backend_include_jpg:n +\cs_new_eq:NN \@@_backend_include_pdf:n \@@_backend_include_jpg:n +\cs_new_eq:NN \@@_backend_include_png:n \@@_backend_include_jpg:n +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_getbb_eps:n, \@@_backend_getbb_ps:n} +% \begin{macro}{\@@_backend_getbb_eps:nm} +% \begin{macro}{\@@_backend_include_eps:n, \@@_backend_include_ps:n} +% \begin{variable} +% {\l_@@_backend_dir_str, \l_@@_backend_name_str, \l_@@_backend_ext_str} +% EPS graphics may be included in \LuaTeX{}/pdfTeX{} by conversion to +% PDF: this requires restricted shell escape. Modelled on the \pkg{epstopdf} +% \LaTeXe{} package, but simplified, conversion takes place here if we have +% shell access. +% \begin{macrocode} +\sys_if_shell:T + { + \str_new:N \l_@@_backend_dir_str + \str_new:N \l_@@_backend_name_str + \str_new:N \l_@@_backend_ext_str + \cs_new_protected:Npn \@@_backend_getbb_eps:n #1 + { + \file_parse_full_name:nNNN {#1} + \l_@@_backend_dir_str + \l_@@_backend_name_str + \l_@@_backend_ext_str + \exp_args:Ne \@@_backend_getbb_eps:nn + { + \exp_args:Ne \__kernel_file_name_quote:n + { + \l_@@_backend_name_str + - \str_tail:N \l_@@_backend_ext_str + -converted-to.pdf + } + } + {#1} + } + \cs_new_eq:NN \@@_backend_getbb_ps:n \@@_backend_getbb_eps:n + \cs_new_protected:Npn \@@_backend_getbb_eps:nn #1#2 + { + \file_compare_timestamp:nNnT {#2} > {#1} + { + \sys_shell_now:n + { repstopdf ~ #2 ~ #1 } + } + \tl_set:Nn \l_@@_final_name_str {#1} + \@@_backend_getbb_pdf:n {#1} + } + \cs_new_protected:Npn \@@_backend_include_eps:n #1 + { + \file_parse_full_name:nNNN {#1} + \l_@@_backend_dir_str \l_@@_backend_name_str \l_@@_backend_ext_str + \exp_args:Ne \@@_backend_include_pdf:n + { + \exp_args:Ne \__kernel_file_name_quote:n + { + \l_@@_backend_name_str + - \str_tail:N \l_@@_backend_ext_str + -converted-to.pdf + } + } + } + \cs_new_eq:NN \@@_backend_include_ps:n \@@_backend_include_eps:n + } +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_get_pagecount:n} +% Simply load and store. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_get_pagecount:n #1 + { + \tex_pdfximage:D {#1} + \int_const:cn { c_@@_ #1 _pages_int } + { \int_use:N \tex_pdflastximagepages:D } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\texttt{dvipdfmx} backend} +% +% \begin{macrocode} +%<*dvipdfmx|xetex> +% \end{macrocode} +% +% \begin{variable}[no-user-doc]{\l_graphics_search_ext_seq} +% \begin{macrocode} +\@@_backend_loaded:n + { + \seq_set_from_clist:Nn \l_graphics_search_ext_seq + { .pdf , .eps , .ps , .png , .jpg , .jpeg , .bmp } + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro} +% { +% \@@_backend_getbb_eps:n , \@@_backend_getbb_ps:n , +% \@@_backend_getbb_jpg:n , \@@_backend_getbb_jpeg:n , +% \@@_backend_getbb_pdf:n , \@@_backend_getbb_png:n , +% \@@_backend_getbb_bmp:n +% } +% Simply use the generic functions: only for \texttt{dvipdfmx} in the +% extraction cases. +% \begin{macrocode} +\@@_backend_loaded:n + { + \cs_new_eq:NN \@@_backend_getbb_eps:n \@@_read_bb:n + \cs_new_eq:NN \@@_backend_getbb_ps:n \@@_read_bb:n + } +%<*dvipdfmx> +\cs_new_protected:Npn \@@_backend_getbb_jpg:n #1 + { + \int_zero:N \l_@@_page_int + \tl_clear:N \l_@@_pagebox_tl + \@@_extract_bb:n {#1} + } +\cs_new_eq:NN \@@_backend_getbb_jpeg:n \@@_backend_getbb_jpg:n +\cs_new_eq:NN \@@_backend_getbb_png:n \@@_backend_getbb_jpg:n +\cs_new_eq:NN \@@_backend_getbb_bmp:n \@@_backend_getbb_jpg:n +\cs_new_protected:Npn \@@_backend_getbb_pdf:n #1 + { + \tl_clear:N \l_@@_decodearray_str + \bool_set_false:N \l_@@_interpolate_bool + \@@_extract_bb:n {#1} + } +% +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\g_@@_track_int} +% Used to track the object number associated with each graphic. +% \begin{macrocode} +\int_new:N \g_@@_track_int +% \end{macrocode} +% \end{variable} +% +% \begin{macro} +% { +% \@@_backend_include_eps:n , \@@_backend_include_ps:n , +% \@@_backend_include_jpg:n , \@@_backend_include_jpseg:n , +% \@@_backend_include_pdf:n , \@@_backend_include_png:n , +% \@@_backend_include_bmp:n , +% } +% \begin{macro}{\@@_backend_include_auxi:nn} +% \begin{macro}{\@@_backend_include_auxii:nnn, \@@_backend_include_auxii:enn} +% \begin{macro}{\@@_backend_include_auxiii:nnn} +% The special syntax depends on the file type. There is a difference in +% how PDF graphics are best handled between |dvipdfmx| and \XeTeX{}: for +% the latter it is better to use the primitive route. The relevant code for +% that is included later in this file. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_include_eps:n #1 + { + \__kernel_backend_literal:e + { + PSfile = #1 \c_space_tl + llx = \dim_to_decimal_in_bp:n \l_@@_llx_dim \c_space_tl + lly = \dim_to_decimal_in_bp:n \l_@@_lly_dim \c_space_tl + urx = \dim_to_decimal_in_bp:n \l_@@_urx_dim \c_space_tl + ury = \dim_to_decimal_in_bp:n \l_@@_ury_dim + } + } +\cs_new_eq:NN \@@_backend_include_ps:n \@@_backend_include_eps:n +\cs_new_protected:Npn \@@_backend_include_jpg:n #1 + { \@@_backend_include_auxi:nn {#1} { image } } +\cs_new_eq:NN \@@_backend_include_jpeg:n \@@_backend_include_jpg:n +\cs_new_eq:NN \@@_backend_include_png:n \@@_backend_include_jpg:n +\cs_new_eq:NN \@@_backend_include_bmp:n \@@_backend_include_jpg:n +%<*dvipdfmx> +\cs_new_protected:Npn \@@_backend_include_pdf:n #1 + { \@@_backend_include_auxi:nn {#1} { epdf } } +% +% \end{macrocode} +% Graphic inclusion is set up to use the fact that each image is stored in +% the PDF as an XObject. This means that we can include repeated images +% only once and refer to them. To allow that, track the nature of each +% image: much the same as for the direct PDF mode case. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_include_auxi:nn #1#2 + { + \@@_backend_include_auxii:enn + { + \tl_if_empty:NF \l_@@_pagebox_tl + { : \l_@@_pagebox_tl } + \int_compare:nNnT \l_@@_page_int > 1 + { :P \int_use:N \l_@@_page_int } + \tl_if_empty:NF \l_@@_decodearray_str + { :D \l_@@_decodearray_str } + \bool_if:NT \l_@@_interpolate_bool + { :I } + } + {#1} {#2} + } +\cs_new_protected:Npn \@@_backend_include_auxii:nnn #1#2#3 + { + \int_if_exist:cTF { c_@@_ #2#1 _int } + { + \__kernel_backend_literal:e + { pdf:usexobj~@graphic \int_use:c { c_@@_ #2#1 _int } } + } + { \@@_backend_include_auxiii:nnn {#2} {#1} {#3} } + } +\cs_generate_variant:Nn \@@_backend_include_auxii:nnn { e } +% \end{macrocode} +% Inclusion using the specials is relatively straight-forward, but there +% is one wrinkle. To get the |pagebox| correct for PDF graphics in all cases, +% it is necessary to provide both that information and the |bbox| argument: +% odd things happen otherwise! +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_include_auxiii:nnn #1#2#3 + { + \int_gincr:N \g_@@_track_int + \int_const:cn { c_@@_ #1#2 _int } { \g_@@_track_int } + \__kernel_backend_literal:e + { + pdf:#3~ + @graphic \int_use:c { c_@@_ #1#2 _int } ~ + \int_compare:nNnT \l_@@_page_int > 1 + { page ~ \int_use:N \l_@@_page_int \c_space_tl } + \tl_if_empty:NF \l_@@_pagebox_tl + { + pagebox ~ \l_@@_pagebox_tl \c_space_tl + bbox ~ + \dim_to_decimal_in_bp:n \l_@@_llx_dim \c_space_tl + \dim_to_decimal_in_bp:n \l_@@_lly_dim \c_space_tl + \dim_to_decimal_in_bp:n \l_@@_urx_dim \c_space_tl + \dim_to_decimal_in_bp:n \l_@@_ury_dim \c_space_tl + } + (#1) + \bool_lazy_or:nnT + { \l_@@_interpolate_bool } + { ! \tl_if_empty_p:N \l_@@_decodearray_str } + { + << + \tl_if_empty:NF \l_@@_decodearray_str + { /Decode~[ \l_@@_decodearray_str ] } + \bool_if:NT \l_@@_interpolate_bool + { /Interpolate~true } + >> + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_get_pagecount:n} +% \begin{macrocode} +%<*dvipdfmx> +\@@_backend_loaded:n + { \cs_new_eq:NN \@@_backend_get_pagecount:n \@@_get_pagecount:n } +% +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\XeTeX{} backend} +% +% \begin{macrocode} +%<*xetex> +% \end{macrocode} +% +% \begin{macro} +% { +% \@@_backend_getbb_jpg:n , +% \@@_backend_getbb_jpeg:n , +% \@@_backend_getbb_pdf:n , +% \@@_backend_getbb_png:n , +% \@@_backend_getbb_bmp:n +% } +% \begin{macro}{\@@_backend_getbb_auxi:nN} +% \begin{macro}{\@@_backend_getbb_auxii:nnN, \@@_backend_getbb_auxii:VnN} +% \begin{macro}{\@@_backend_getbb_auxiii:nNnn} +% \begin{macro}{\@@_backend_getbb_auxiv:nnNnn, \@@_backend_getbb_auxiv:VnNnn} +% \begin{macro}{\@@_backend_getbb_auxv:nNnn, \@@_backend_getbb_auxv:nNnn} +% \begin{macro}[EXP]{\@@_backend_getbb_pagebox:w} +% For \XeTeX{}, there are two primitives that allow us to obtain +% the bounding box without needing \texttt{extractbb}. The only complexity +% is passing the various minor variations to a common core process. The +% \XeTeX{} primitive omits the text |box| from the page box specification, +% so there is also some \enquote{trimming} to do here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_getbb_jpg:n #1 + { + \int_zero:N \l_@@_page_int + \tl_clear:N \l_@@_pagebox_tl + \@@_backend_getbb_auxi:nN {#1} \tex_XeTeXpicfile:D + } +\cs_new_eq:NN \@@_backend_getbb_jpeg:n \@@_backend_getbb_jpg:n +\cs_new_eq:NN \@@_backend_getbb_png:n \@@_backend_getbb_jpg:n +\cs_new_eq:NN \@@_backend_getbb_bmp:n \@@_backend_getbb_jpg:n +\cs_new_protected:Npn \@@_backend_getbb_pdf:n #1 + { + \tl_clear:N \l_@@_decodearray_str + \bool_set_false:N \l_@@_interpolate_bool + \@@_backend_getbb_auxi:nN {#1} \tex_XeTeXpdffile:D + } +\cs_new_protected:Npn \@@_backend_getbb_auxi:nN #1#2 + { + \int_compare:nNnTF \l_@@_page_int > 1 + { \@@_backend_getbb_auxii:VnN \l_@@_page_int {#1} #2 } + { \@@_backend_getbb_auxiii:nNnn {#1} #2 { :P 1 } { page 1 } } + } +\cs_new_protected:Npn \@@_backend_getbb_auxii:nnN #1#2#3 + { \@@_backend_getbb_auxiii:nNnn {#2} #3 { :P #1 } { page #1 } } +\cs_generate_variant:Nn \@@_backend_getbb_auxii:nnN { V } +\cs_new_protected:Npn \@@_backend_getbb_auxiii:nNnn #1#2#3#4 + { + \tl_if_empty:NTF \l_@@_pagebox_tl + { \@@_backend_getbb_auxiv:VnNnn \l_@@_pagebox_tl } + { \@@_backend_getbb_auxv:nNnn } + {#1} #2 {#3} {#4} + } +\cs_new_protected:Npn \@@_backend_getbb_auxiv:nnNnn #1#2#3#4#5 + { + \use:e + { + \@@_backend_getbb_auxv:nNnn {#2} #3 { : #1 #4 } + { + #5 + \tl_if_blank:nF {#1} + { \c_space_tl \@@_backend_getbb_pagebox:w #1 } + } + } + } +\cs_generate_variant:Nn \@@_backend_getbb_auxiv:nnNnn { V } +\cs_new_protected:Npn \@@_backend_getbb_auxv:nNnn #1#2#3#4 + { + \@@_bb_restore:nF {#1#3} + { \@@_backend_getbb_auxvi:nNnn {#1} #2 {#3} {#4} } + } +\cs_new_protected:Npn \@@_backend_getbb_auxvi:nNnn #1#2#3#4 + { + \hbox_set:Nn \l_@@_internal_box { #2 #1 ~ #4 } + \dim_set:Nn \l_@@_urx_dim { \box_wd:N \l_@@_internal_box } + \dim_set:Nn \l_@@_ury_dim { \box_ht:N \l_@@_internal_box } + \@@_bb_save:n {#1#3} + } +\cs_new:Npn \@@_backend_getbb_pagebox:w #1 box {#1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_include_pdf:n} +% For PDF graphics, properly supporting the |pagebox| concept in \XeTeX{} +% is best done using the |\tex_XeTeXpdffile:D| primitive. The syntax here +% is the same as for the graphic measurement part, although we know at this +% stage that there must be some valid setting for \cs{l_@@_pagebox_tl}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_include_pdf:n #1 + { + \tex_XeTeXpdffile:D #1 ~ + \int_compare:nNnT \l_@@_page_int > 0 + { page ~ \int_use:N \l_@@_page_int \c_space_tl } + \exp_after:wN \@@_backend_getbb_pagebox:w \l_@@_pagebox_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_get_pagecount:n} +% Very little to do here other than cover the case of a non-PDF file. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_get_pagecount:n #1 + { + \int_const:cn { c_@@_ #1 _pages_int } + { + \int_max:nn + { \int_use:N \tex_XeTeXpdfpagecount:D #1 ~ } + { 1 } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\texttt{dvisvgm} backend} +% +% \begin{macrocode} +%<*dvisvgm> +% \end{macrocode} +% +% \begin{variable}[no-user-doc]{\l_graphics_search_ext_seq} +% \begin{macrocode} +\@@_backend_loaded:n + { + \seq_set_from_clist:Nn + \l_graphics_search_ext_seq + { .svg , .pdf , .eps , .ps , .png , .jpg , .jpeg } + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_backend_getbb_svg:n} +% \begin{macro}{\@@_backend_getbb_svg_auxi:nNn} +% \begin{macro}{\@@_backend_getbb_svg_auxii:w} +% \begin{macro} +% { +% \@@_backend_getbb_svg_auxiii:Nw , +% \@@_backend_getbb_svg_auxiv:Nw , +% \@@_backend_getbb_svg_auxv:Nw +% } +% \begin{macro}{\@@_backend_getbb_svg_auxvi:Nn} +% \begin{macro}{\@@_backend_getbb_svg_auxvii:w} +% This is relatively similar to reading bounding boxes for |.eps| files. Life +% is though made more tricky as we cannot pick a single line for the data. So +% we have to loop until we collect up both height and width. To do that, we +% can use a marker value. We also have to allow for the default units of the +% lengths: they are big points and may be omitted. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_getbb_svg:n #1 + { + \@@_bb_restore:nF {#1} + { + \ior_open:Nn \l_@@_internal_ior {#1} + \ior_if_eof:NTF \l_@@_internal_ior + { \msg_error:nnn { graphics } { graphic-not-found } {#1} } + { + \dim_zero:N \l_@@_llx_dim + \dim_zero:N \l_@@_lly_dim + \dim_set:Nn \l_@@_urx_dim { -\c_max_dim } + \dim_set:Nn \l_@@_ury_dim { -\c_max_dim } + \ior_str_map_inline:Nn \l_@@_internal_ior + { + \dim_compare:nNnT \l_@@_urx_dim = { -\c_max_dim } + { + \@@_backend_getbb_svg_auxi:nNn + { width } \l_@@_urx_dim {##1} + } + \dim_compare:nNnT \l_@@_ury_dim = { -\c_max_dim } + { + \@@_backend_getbb_svg_auxi:nNn + { height } \l_@@_ury_dim {##1} + } + \bool_lazy_and:nnF + { \dim_compare_p:nNn \l_@@_urx_dim = { -\c_max_dim } } + { \dim_compare_p:nNn \l_@@_ury_dim = { -\c_max_dim } } + { \ior_map_break: } + } + \@@_bb_save:n {#1} + } + \ior_close:N \l_@@_internal_ior + } + } +\cs_new_protected:Npn \@@_backend_getbb_svg_auxi:nNn #1#2#3 + { + \use:e + { + \cs_set_protected:Npn \@@_backend_getbb_svg_auxii:w + ##1 \tl_to_str:n {#1} = ##2 \tl_to_str:n {#1} = ##3 + \s_@@_stop + } + { + \tl_if_blank:nF {##2} + { + \peek_remove_spaces:n + { + \peek_meaning:NTF ' % ' + { \@@_backend_getbb_svg_auxiii:Nw #2 } + { + \peek_meaning:NTF " % " + { \@@_backend_getbb_svg_auxiv:Nw #2 } + { \@@_backend_getbb_svg_auxv:Nw #2 } + } + } + ##2 \s_@@_stop + } + } + \use:e + { + \@@_backend_getbb_svg_auxii:w #3 + \tl_to_str:n {#1} = \tl_to_str:n {#1} = + \s_@@_stop + } + } +\cs_new_protected:Npn \@@_backend_getbb_svg_auxii:w { } +\cs_new_protected:Npn \@@_backend_getbb_svg_auxiii:Nw #1 ' #2 ' #3 \s_@@_stop + { \@@_backend_getbb_svg_auxvi:Nn #1 {#2} } +\cs_new_protected:Npn \@@_backend_getbb_svg_auxiv:Nw #1 " #2 " #3 \s_@@_stop + { \@@_backend_getbb_svg_auxvi:Nn #1 {#2} } +\cs_new_protected:Npn \@@_backend_getbb_svg_auxv:Nw #1 #2 ~ #3 \s_@@_stop + { \@@_backend_getbb_svg_auxvi:Nn #1 {#2} } +\cs_new_protected:Npn \@@_backend_getbb_svg_auxvi:Nn #1#2 + { + \tex_afterassignment:D \@@_backend_getbb_svg_auxvii:w + \l_@@_internal_dim #2 bp \scan_stop: + \dim_set_eq:NN #1 \l_@@_internal_dim + } +\cs_new_protected:Npn \@@_backend_getbb_svg_auxvii:w #1 \scan_stop: { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_getbb_eps:n, \@@_backend_getbb_ps:n} +% Simply use the generic function. +% \begin{macrocode} +\@@_backend_loaded:n + { + \cs_new_eq:NN \@@_backend_getbb_eps:n \@@_read_bb:n + \cs_new_eq:NN \@@_backend_getbb_ps:n \@@_read_bb:n + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_getbb_png:n, \@@_backend_getbb_jpg:n, \@@_backend_getbb_jpeg:n} +% These can be included by extracting the bounding box data. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_getbb_jpg:n #1 + { + \int_zero:N \l_@@_page_int + \tl_clear:N \l_@@_pagebox_tl + \@@_extract_bb:n {#1} + } +\cs_new_eq:NN \@@_backend_getbb_jpeg:n \@@_backend_getbb_jpg:n +\cs_new_eq:NN \@@_backend_getbb_png:n \@@_backend_getbb_jpg:n +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_getbb_pdf:n} +% Same as for \texttt{dvipdfmx}: use the generic function +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_getbb_pdf:n #1 + { + \tl_clear:N \l_@@_decodearray_str + \bool_set_false:N \l_@@_interpolate_bool + \@@_extract_bb:n {#1} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_include_eps:n , +% \@@_backend_include_ps:n , +% \@@_backend_include_pdf:n +% } +% \begin{macro}{\@@_backend_include:nn} +% The special syntax is relatively clear here: remember we need PostScript +% sizes here. (This is the same as the \texttt{dvips} code.) +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_include_eps:n #1 + { \@@_backend_include:nn { PSfile } {#1} } +\cs_new_eq:NN \@@_backend_include_ps:n \@@_backend_include_eps:n +\cs_new_protected:Npn \@@_backend_include_pdf:n #1 + { \@@_backend_include:nn { pdffile } {#1} } +\cs_new_protected:Npn \@@_backend_include:nn #1#2 + { + \__kernel_backend_literal:e + { + #1 = #2 \c_space_tl + llx = \dim_to_decimal_in_bp:n \l_@@_llx_dim \c_space_tl + lly = \dim_to_decimal_in_bp:n \l_@@_lly_dim \c_space_tl + urx = \dim_to_decimal_in_bp:n \l_@@_urx_dim \c_space_tl + ury = \dim_to_decimal_in_bp:n \l_@@_ury_dim + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_include_svg:n , +% \@@_backend_include_png:n , +% \@@_backend_include_jpg:n , +% \@@_backend_include_jpeg:n +% } +% \begin{macro}{\@@_backend_include_dequote:w} +% The backend here has built-in support for basic graphic inclusion (see +% \texttt{dvisvgm.def} for a more complex approach, needed if clipping, +% \emph{etc.}, is covered at the graphic backend level). We have to deal +% with the fact that the image reference point is at the \emph{top}, so +% there is a need for a vertical shift to put it in the right place. +% The other issue is that |#1| must be quote-corrected. The +% \texttt{dvisvgm:img} operation quotes the file name, but if it is already +% quoted (contains spaces) then we have an issue: we simply strip off any +% quotes as a result. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_include_svg:n #1 + { + \box_move_up:nn { \l_@@_ury_dim } + { + \hbox:n + { + \__kernel_backend_literal:e + { + dvisvgm:img~ + \dim_to_decimal:n { \l_@@_urx_dim } ~ + \dim_to_decimal:n { \l_@@_ury_dim } ~ + \@@_backend_include_dequote:w #1 " #1 " \s_@@_stop + } + } + } + } +\cs_new_eq:NN \@@_backend_include_png:n \@@_backend_include_svg:n +\cs_new_eq:NN \@@_backend_include_jpeg:n \@@_backend_include_svg:n +\cs_new_eq:NN \@@_backend_include_jpg:n \@@_backend_include_svg:n +\cs_new:Npn \@@_backend_include_dequote:w #1 " #2 " #3 \s_@@_stop + {#2} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_get_pagecount:n} +% \begin{macrocode} +\@@_backend_loaded:n + { \cs_new_eq:NN \@@_backend_get_pagecount:n \@@_get_pagecount:n } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex-dev/l3backend/l3backend-header.dtx b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-header.dtx new file mode 100644 index 00000000000..486f5648224 --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-header.dtx @@ -0,0 +1,590 @@ +% \iffalse meta-comment +% +%% File: l3backend-header.dtx +% +% Copyright (C) 2019-2024 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} +% +% \fi +% +% \title{^^A +% The \pkg{l3backend-header} module\\ Backend graphics support^^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 2024-04-11} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3backend-header} implementation} +% +% \begin{macrocode} +%<*dvips&header> +% \end{macrocode} +% +% \begin{macro}[no-user-doc]{color.sc} +% Empty definition for color at the top level. +% \begin{macrocode} +/color.sc { } def +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{TeXcolorseparation, separation} +% Support for separation/spot colors: this strange naming is so +% things work with the color stack. +% \begin{macrocode} +TeXDict begin +/TeXcolorseparation { setcolor } def +end +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{pdf.globaldict} +% A small global dictionary for backend use. +% \begin{macrocode} +true setglobal +/pdf.globaldict 4 dict def +false setglobal +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int] +% { +% pdf.cvs , +% pdf.dvi.pt , +% pdf.pt.dvi , +% pdf.rect.ht +% } +% Small utilities for PostScript manipulations. Conversion to DVI dimensions +% is done here to allow for |Resolution|. The total height of a rectangle +% (an array) needs a little maths, in contrast to simply extracting a value. +% \begin{macrocode} +/pdf.cvs { 65534 string cvs } def +/pdf.dvi.pt { 72.27 mul Resolution div } def +/pdf.pt.dvi { 72.27 div Resolution mul } def +/pdf.rect.ht { dup 1 get neg exch 3 get add } def +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{pdf.linkmargin, pdf.linkdp.pad, pdf.linkht.pad} +% Settings which are defined up-front in |SDict|. +% \begin{macrocode} +/pdf.linkmargin { 1 pdf.pt.dvi } def +/pdf.linkdp.pad { 0 } def +/pdf.linkht.pad { 0 } def +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int] +% { +% pdf.rect , +% pdf.save.ll , +% pdf.save.ur , +% pdf.save.linkll , +% pdf.save.linkur , +% pdf.llx , +% pdf.lly , +% pdf.urx , +% pdf.ury +% } +% Functions for marking the limits of an annotation/link, plus drawing the +% border. We separate links for generic annotations to support adding a +% margin and setting a minimal size. +% \begin{macrocode} +/pdf.rect + { /Rect [ pdf.llx pdf.lly pdf.urx pdf.ury ] } def +/pdf.save.ll + { + currentpoint + /pdf.lly exch def + /pdf.llx exch def + } + def +/pdf.save.ur + { + currentpoint + /pdf.ury exch def + /pdf.urx exch def + } + def +/pdf.save.linkll + { + currentpoint + pdf.linkmargin add + pdf.linkdp.pad add + /pdf.lly exch def + pdf.linkmargin sub + /pdf.llx exch def + } + def +/pdf.save.linkur + { + currentpoint + pdf.linkmargin sub + pdf.linkht.pad sub + /pdf.ury exch def + pdf.linkmargin add + /pdf.urx exch def + } + def +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int] +% { +% pdf.dest.anchor , +% pdf.dest.x , +% pdf.dest.y , +% pdf.dest.point , +% pdf.dest2device , +% pdf.dev.x , +% pdf.dev.y , +% pdf.tmpa , +% pdf.tmpb , +% pdf.tmpc , +% pdf.tmpd +% } +% For finding the anchor point of a destination link. We make the use case +% a separate function as it comes up a lot, and as this makes it easier to +% adjust if we need additional effects. We also need a more complex approach +% to convert a co-ordinate pair correctly when defining a rectangle: this +% can otherwise be out when using a landscape page. (Thanks to Alexander +% Grahn for the approach here.) +% \begin{macrocode} +/pdf.dest.anchor + { + currentpoint exch + pdf.dvi.pt 72 add + /pdf.dest.x exch def + pdf.dvi.pt + vsize 72 sub exch sub + /pdf.dest.y exch def + } + def +/pdf.dest.point + { pdf.dest.x pdf.dest.y } def +/pdf.dest2device + { + /pdf.dest.y exch def + /pdf.dest.x exch def + matrix currentmatrix + matrix defaultmatrix + matrix invertmatrix + matrix concatmatrix + cvx exec + /pdf.dev.y exch def + /pdf.dev.x exch def + /pdf.tmpd exch def + /pdf.tmpc exch def + /pdf.tmpb exch def + /pdf.tmpa exch def + pdf.dest.x pdf.tmpa mul + pdf.dest.y pdf.tmpc mul add + pdf.dev.x add + pdf.dest.x pdf.tmpb mul + pdf.dest.y pdf.tmpd mul add + pdf.dev.y add + } + def +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int] +% { +% pdf.bordertracking , +% pdf.bordertracking.begin , +% pdf.bordertracking.end , +% pdf.leftboundary , +% pdf.rightboundary , +% pdf.brokenlink.rect , +% pdf.brokenlink.skip , +% pdf.brokenlink.dict , +% pdf.bordertracking.endpage , +% pdf.bordertracking.continue , +% pdf.originx , +% pdf.originy +% } +% To know where a breakable link can go, we need to track the boundary +% rectangle. That can be done by hooking into |a| and |x| operations: +% those names have to be retained. The boundary is stored at the end of +% the operation. Special effort is needed at the start and end of pages +% (or rather galleys), such that everything works properly. +% \begin{macrocode} +/pdf.bordertracking false def +/pdf.bordertracking.begin + { + SDict /pdf.bordertracking true put + SDict /pdf.leftboundary undef + SDict /pdf.rightboundary undef + /a where + { + /a + { + currentpoint pop + SDict /pdf.rightboundary known dup + { + SDict /pdf.rightboundary get 2 index lt + { not } + if + } + if + { pop } + { SDict exch /pdf.rightboundary exch put } + ifelse + moveto + currentpoint pop + SDict /pdf.leftboundary known dup + { + SDict /pdf.leftboundary get 2 index gt + { not } + if + } + if + { pop } + { SDict exch /pdf.leftboundary exch put } + ifelse + } + put + } + if + } + def +/pdf.bordertracking.end + { + /a where { /a { moveto } put } if + /x where { /x { 0 exch rmoveto } put } if + SDict /pdf.leftboundary known + { pdf.outerbox 0 pdf.leftboundary put } + if + SDict /pdf.rightboundary known + { pdf.outerbox 2 pdf.rightboundary put } + if + SDict /pdf.bordertracking false put + } + def + /pdf.bordertracking.endpage +{ + pdf.bordertracking + { + pdf.bordertracking.end + true setglobal + pdf.globaldict + /pdf.brokenlink.rect [ pdf.outerbox aload pop ] put + pdf.globaldict + /pdf.brokenlink.skip pdf.baselineskip put + pdf.globaldict + /pdf.brokenlink.dict + pdf.link.dict pdf.cvs put + false setglobal + mark pdf.link.dict cvx exec /Rect + [ + pdf.llx + pdf.lly + pdf.outerbox 2 get pdf.linkmargin add + currentpoint exch pop + pdf.outerbox pdf.rect.ht sub pdf.linkmargin sub + ] + /ANN pdf.pdfmark + } + if +} + def +/pdf.bordertracking.continue + { + /pdf.link.dict pdf.globaldict + /pdf.brokenlink.dict get def + /pdf.outerbox pdf.globaldict + /pdf.brokenlink.rect get def + /pdf.baselineskip pdf.globaldict + /pdf.brokenlink.skip get def + pdf.globaldict dup dup + /pdf.brokenlink.dict undef + /pdf.brokenlink.skip undef + /pdf.brokenlink.rect undef + currentpoint + /pdf.originy exch def + /pdf.originx exch def + /a where + { + /a + { + moveto + SDict + begin + currentpoint pdf.originy ne exch + pdf.originx ne or + { + pdf.save.linkll + /pdf.lly + pdf.lly pdf.outerbox 1 get sub def + pdf.bordertracking.begin + } + if + end + } + put + } + if + /x where + { + /x + { + 0 exch rmoveto + SDict + begin + currentpoint + pdf.originy ne exch pdf.originx ne or + { + pdf.save.linkll + /pdf.lly + pdf.lly pdf.outerbox 1 get sub def + pdf.bordertracking.begin + } + if + end + } + put + } + if + } + def +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int] +% { +% pdf.breaklink , +% pdf.breaklink.write , +% pdf.count , +% pdf.currentrect +% } +% Dealing with link breaking itself has multiple stage. The first step is to +% find the |Rect| entry in the dictionary, looping over key--value pairs. +% The first line is handled first, adjusting the rectangle to stay inside the +% text area. The second phase is a loop over the height of the bulk of the +% link area, done on the basis of a number of baselines. Finally, the end of +% the link area is tidied up, again from the boundary of the text area. +% \begin{macrocode} +/pdf.breaklink + { + pop + counttomark 2 mod 0 eq + { + counttomark /pdf.count exch def + { + pdf.count 0 eq { exit } if + counttomark 2 roll + 1 index /Rect eq + { + dup 4 array copy + dup dup + 1 get + pdf.outerbox pdf.rect.ht + pdf.linkmargin 2 mul add sub + 3 exch put + dup + pdf.outerbox 2 get + pdf.linkmargin add + 2 exch put + dup dup + 3 get + pdf.outerbox pdf.rect.ht + pdf.linkmargin 2 mul add add + 1 exch put + /pdf.currentrect exch def + pdf.breaklink.write + { + pdf.currentrect + dup + pdf.outerbox 0 get + pdf.linkmargin sub + 0 exch put + dup + pdf.outerbox 2 get + pdf.linkmargin add + 2 exch put + dup dup + 1 get + pdf.baselineskip add + 1 exch put + dup dup + 3 get + pdf.baselineskip add + 3 exch put + /pdf.currentrect exch def + pdf.breaklink.write + } + 1 index 3 get + pdf.linkmargin 2 mul add + pdf.outerbox pdf.rect.ht add + 2 index 1 get sub + pdf.baselineskip div round cvi 1 sub + exch + repeat + pdf.currentrect + dup + pdf.outerbox 0 get + pdf.linkmargin sub + 0 exch put + dup dup + 1 get + pdf.baselineskip add + 1 exch put + dup dup + 3 get + pdf.baselineskip add + 3 exch put + dup 2 index 2 get 2 exch put + /pdf.currentrect exch def + pdf.breaklink.write + SDict /pdf.pdfmark.good false put + exit + } + { pdf.count 2 sub /pdf.count exch def } + ifelse + } + loop + } + if + /ANN + } + def +/pdf.breaklink.write + { + counttomark 1 sub + index /_objdef eq + { + counttomark -2 roll + dup wcheck + { + readonly + counttomark 2 roll + } + { pop pop } + ifelse + } + if + counttomark 1 add copy + pop pdf.currentrect + /ANN pdfmark + } + def +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int] +% { +% pdf.pdfmark , +% pdf.pdfmark.good , +% pdf.outerbox , +% pdf.baselineskip , +% pdf.pdfmark.dict +% } +% The business end of breaking links starts by hooking into |pdfmarks|. +% Unlike \pkg{hypdvips}, we avoid altering any links we have not created +% by using a copy of the core |pdfmarks| function. Only mark types which +% are known are altered. At present, this is purely |ANN| marks, which are +% measured relative to the size of the baseline skip. If they are +% more than one apparent line high, breaking is applied. +% \begin{macrocode} +/pdf.pdfmark + { + SDict /pdf.pdfmark.good true put + dup /ANN eq + { + pdf.pdfmark.store + pdf.pdfmark.dict + begin + Subtype /Link eq + currentdict /Rect known and + SDict /pdf.outerbox known and + SDict /pdf.baselineskip known and + { + Rect 3 get + pdf.linkmargin 2 mul add + pdf.outerbox pdf.rect.ht add + Rect 1 get sub + pdf.baselineskip div round cvi 0 gt + { pdf.breaklink } + if + } + if + end + SDict /pdf.outerbox undef + SDict /pdf.baselineskip undef + currentdict /pdf.pdfmark.dict undef + } + if + pdf.pdfmark.good + { pdfmark } + { cleartomark } + ifelse + } + def +/pdf.pdfmark.store + { + /pdf.pdfmark.dict 65534 dict def + counttomark 1 add copy + pop + { + dup mark eq + { + pop + exit + } + { + pdf.pdfmark.dict + begin def end + } + ifelse + } + loop +} + def +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex-dev/l3backend/l3backend-opacity.dtx b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-opacity.dtx new file mode 100644 index 00000000000..0c29574c377 --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-opacity.dtx @@ -0,0 +1,353 @@ +% \iffalse meta-comment +% +%% File: l3backend-opacity.dtx +% +% Copyright (C) 2021-2024 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} +% +% \fi +% +% \title{^^A +% The \pkg{l3backend-opacity} module\\ Backend opacity support^^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 2024-04-11} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3backend-opacity} implementation} +% +% \begin{macrocode} +%<*package> +%<@@=opacity> +% \end{macrocode} +% +% Although opacity is not color, it needs to be managed in a somewhat +% similar way: using a dedicated stack if possible. Depending on the backend, +% that may not be possible. There is also the need to cover fill/stroke setting +% as well as more general running opacity. It is easiest to describe the value +% used in terms of opacity, although commonly this is referred to as +% transparency. +% +% \begin{macrocode} +%<*dvips> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_select:n} +% \begin{macro}{\@@_backend_fill:n, \@@_backend_stroke:n} +% \begin{macro}{\@@_backend:nnn} +% No stack so set values directly. The need to deal with Distiller and +% Ghostscript separately means we use a common auxiliary: the two +% systems require different PostScript for transparency. This is +% of course not quite as efficient as doing one test for setting all +% transparency, but it keeps things clearer here. Thanks to Alex Grahn +% for the detail on testing for GhostScript. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select:n #1 + { + \@@_backend:nnn {#1} { fill } { ca } + \@@_backend:nnn {#1} { stroke } { CA } + } +\cs_new_protected:Npn \@@_backend_fill:n #1 + { + \@@_backend:nnn + { #1 } + { fill } + { ca } + } +\cs_new_protected:Npn \@@_backend_stroke:n #1 + { + \@@_backend:nnn + { #1 } + { stroke } + { CA } + } +\cs_new_protected:Npn \@@_backend:nnn #1#2#3 + { + \__kernel_backend_postscript:n + { + product ~ (Ghostscript) ~ search + { + pop ~ pop ~ pop ~ + #1 ~ .set #2 constantalpha + } + { + pop ~ + mark ~ + /#3 ~ #1 + /SetTransparency ~ + pdfmark + } + ifelse + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dvipdfmx|luatex|pdftex|xetex> +% \end{macrocode} +% +% \begin{variable}{\c_@@_backend_stack_int} +% Set up a stack, where that is applicable. +% \begin{macrocode} +\bool_lazy_and:nnT + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { +%<*luatex|pdftex> + \__kernel_color_backend_stack_init:Nnn \c_@@_backend_stack_int + { page ~ direct } { /opacity 1 ~ gs } +% + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity 1 } { << /ca ~ 1 /CA ~ 1 >> } + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_backend_fill_tl, \l_@@_backend_stroke_tl} +% We use |tl| here for speed: at the backend, this should be reasonable. +% Both need to start off fully opaque. +% \begin{macrocode} +\tl_new:N \l_@@_backend_fill_tl +\tl_new:N \l_@@_backend_stroke_tl +\tl_set:Nn \l_@@_backend_fill_tl { 1 } +\tl_set:Nn \l_@@_backend_stroke_tl { 1 } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_backend_select:n} +% \begin{macro}{\@@_backend_reset:} +% Much the same as color. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select:n #1 + { + \tl_set:Nn \l_@@_backend_fill_tl {#1} + \tl_set:Nn \l_@@_backend_stroke_tl {#1} + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity #1 } + { << /ca ~ #1 /CA ~ #1 >> } +%<*dvipdfmx|xetex> + \__kernel_backend_literal_pdf:n +% +%<*luatex|pdftex> + \__kernel_color_backend_stack_push:nn \c_@@_backend_stack_int +% + { /opacity #1 ~ gs } + \group_insert_after:N \@@_backend_reset: + } +\cs_new_protected:Npn \@@_backend_reset: + { +%<*dvipdfmx|xetex> + \__kernel_backend_literal_pdf:n + { /opacity1 ~ gs } +% +%<*luatex|pdftex> + \__kernel_color_backend_stack_pop:n \c_@@_backend_stack_int +% + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_fill:n, \@@_backend_stroke:n} +% \begin{macro}{\@@_backend_fill_stroke:nn} +% For separate fill and stroke, we need to work out if we need to do +% more work or if we can stick to a single setting. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_fill:n #1 + { + \exp_args:Nno \@@_backend_fill_stroke:nn + { #1 } + { \l_@@_backend_stroke_tl } + } +\cs_new_protected:Npn \@@_backend_stroke:n #1 + { + \exp_args:No \@@_backend_fill_stroke:nn + { \l_@@_backend_fill_tl } + { #1 } + } +\cs_new_protected:Npn \@@_backend_fill_stroke:nn #1#2 + { + \str_if_eq:nnTF {#1} {#2} + { \@@_backend_select:n {#1} } + { + \tl_set:Nn \l_@@_backend_fill_tl {#1} + \tl_set:Nn \l_@@_backend_stroke_tl {#2} + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity.fill #1 } + { << /ca ~ #1 >> } + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity.stroke #2 } + { << /CA ~ #2 >> } +%<*dvipdfmx|xetex> + \__kernel_backend_literal_pdf:n +% +%<*luatex|pdftex> + \__kernel_color_backend_stack_push:nn \c_@@_backend_stack_int +% + { /opacity.fill #1 ~ gs /opacity.stroke #2 ~ gs } + \group_insert_after:N \@@_backend_reset: + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_select:n, \@@_backend_fill_stroke:nn} +% Redefine them to stubs if pdfmanagement is either not loaded or +% deactivated. +% \begin{macrocode} +\bool_lazy_and:nnF + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \cs_gset_protected:Npn \@@_backend_select:n #1 { } + \cs_gset_protected:Npn \@@_backend_fill_stroke:nn #1#2 { } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dvisvgm> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_select:n, \@@_backend_fill:n, \@@_backend_stroke:n} +% \begin{macro}{\@@_backend:nn} +% Once again, we use a scope here. There is a general opacity function for +% SVG, but that is of course not set up using the stack. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_select:n #1 + { \@@_backend:nn {#1} { } } +\cs_new_protected:Npn \@@_backend_fill:n #1 + { \@@_backend:nn {#1} { fill- } } +\cs_new_protected:Npn \@@_backend_stroke:n #1 + { \@@_backend:nn {#1} { stroke- } } +\cs_new_protected:Npn \@@_backend:nn #1#2 + { \__kernel_backend_scope:e { #2 opacity = " #1 " } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{Font handling integration} +% +% In \LuaTeX{} we want to use these functions also for transparent fonts +% to avoid interference between both uses of transparency. +% +% \begin{macrocode} +%<*lua> +% \end{macrocode} +% +% First we need to check if pdfmanagement is active from Lua. +% \begin{macrocode} +local pdfmanagement_active do + local pdfmanagement_if_active_p = token.create'pdfmanagement_if_active_p:' + local cmd = pdfmanagement_if_active_p.cmdname + if cmd == 'undefined_cs' then + pdfmanagement_active = false + else + token.put_next(pdfmanagement_if_active_p) + pdfmanagement_active = token.scan_int() ~= 0 + end +end + +if pdfmanagement_active and luaotfload and luaotfload.set_transparent_colorstack then + luaotfload.set_transparent_colorstack(function() return token.create'c_@@_backend_stack_int'.index end) + + local transparent_register = { + token.create'pdfmanagement_add:nnn', + token.new(0, 1), + 'Page/Resources/ExtGState', + token.new(0, 2), + token.new(0, 1), + '', + token.new(0, 2), + token.new(0, 1), + '<>', + token.new(0, 2), + } + luatexbase.add_to_callback('luaotfload.parse_transparent', function(value) + value = (octet * -1):match(value) + if not value then + tex.error'Invalid transparency value' + return + end + value = value:sub(1, -2) + local result = 'opacity' .. value + tex.runtoks(function() + transparent_register[6], transparent_register[10], transparent_register[12] = result, value, value + tex.sprint(-2, transparent_register) + end) + return '/' .. result .. ' gs' + end, 'l3opacity') +end +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdf.dtx b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdf.dtx new file mode 100644 index 00000000000..cf09c0eec22 --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/l3backend/l3backend-pdf.dtx @@ -0,0 +1,1755 @@ +% \iffalse meta-comment +% +%% File: l3backend-pdf.dtx +% +% Copyright (C) 2019-2024 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} +% +% \fi +% +% \title{^^A +% The \pkg{l3backend-pdf} module\\ Backend PDF features^^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 2024-04-11} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3backend-pdf} implementation} +% +% \begin{macrocode} +%<*package> +%<@@=pdf> +% \end{macrocode} +% +% Setting up PDF resources is a complex area with only limited documentation +% in the engine manuals. The following code builds heavily on existing ideas +% from \pkg{hyperref} work by Sebastian Rahtz and Heiko Oberdiek, and +% 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} +% +% \end{macrocode} +% +% \subsection{\texttt{dvips} backend} +% +% \begin{macrocode} +%<*dvips> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_pdfmark:n, \@@_backend_pdfmark:e} +% Used often enough it should be a separate function. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_pdfmark:n #1 + { \__kernel_backend_postscript:n { mark #1 ~ pdfmark } } +\cs_generate_variant:Nn \@@_backend_pdfmark:n { e } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Catalogue entries} +% +% \begin{macro}{\@@_backend_catalog_gput:nn, \@@_backend_info_gput:nn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_catalog_gput:nn #1#2 + { \@@_backend_pdfmark:n { { Catalog } << /#1 ~ #2 >> /PUT } } +\cs_new_protected:Npn \@@_backend_info_gput:nn #1#2 + { \@@_backend_pdfmark:n { /#1 ~ #2 /DOCINFO } } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Objects} +% +% \begin{macro}{\@@_backend_object_new:} +% \begin{macro}[EXP]{\@@_backend_object_ref:n, \@@_backend_object_id:n} +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_object_new: + { \int_gincr:N \g_@@_backend_object_int } +\cs_new:Npn \@@_backend_object_ref:n #1 { { pdf.obj #1 } } +\cs_new_eq:NN \@@_backend_object_id:n \@@_backend_object_ref:n +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \@@_backend_object_write:nnn, \@@_backend_object_write:nne, +% \@@_backend_object_write_aux:nnn +% } +% \begin{macro} +% { +% \@@_backend_object_write_array:nn , +% \@@_backend_object_write_dict:nn , +% \@@_backend_object_write_fstream:nn , +% \@@_backend_object_write_stream:nn +% } +% \begin{macro}{\@@_backend_object_write_stream:nnn} +% This is where we choose the actual type: some work to get things +% right. To allow code sharing with the anonymous version, we use an +% auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_object_write:nnn #1#2#3 + { + \@@_backend_object_write_aux:nnn + { \@@_backend_object_ref:n {#1} } + {#2} {#3} + } +\cs_generate_variant:Nn \@@_backend_object_write:nnn { nne } +\cs_new_protected:Npn \@@_backend_object_write_aux:nnn #1#2#3 + { + \@@_backend_pdfmark:e + { + /_objdef ~ #1 + /type + \str_case:nn {#2} + { + { array } { /array } + { dict } { /dict } + { fstream } { /stream } + { stream } { /stream } + } + /OBJ + } + \use:c { @@_backend_object_write_ #2 :nn } {#1} {#3} + } +\cs_new_protected:Npn \@@_backend_object_write_array:nn #1#2 + { + \@@_backend_pdfmark:e + { #1 ~0~ [ ~ \exp_not:n {#2} ~ ] ~ /PUTINTERVAL } + } +\cs_new_protected:Npn \@@_backend_object_write_dict:nn #1#2 + { + \@@_backend_pdfmark:e + { #1 << \exp_not:n {#2} >> /PUT } + } +\cs_new_protected:Npn \@@_backend_object_write_fstream:nn #1#2 + { + \exp_args:Ne + \@@_backend_object_write_fstream:nnn {#1} #2 + } +\cs_new_protected:Npn \@@_backend_object_write_fstream:nnn #1#2#3 + { + \__kernel_backend_postscript:n + { + SDict ~ begin ~ + mark ~ #1 ~ << #2 >> /PUT ~ pdfmark ~ + mark ~ #1 ~ ( #3 )~ ( r )~ file ~ /PUT ~ pdfmark ~ + end + } + } +\cs_new_protected:Npn \@@_backend_object_write_stream:nn #1#2 + { + \exp_args:Ne + \@@_backend_object_write_stream:nnn {#1} #2 + } +\cs_new_protected:Npn \@@_backend_object_write_stream:nnn #1#2#3 + { + \__kernel_backend_postscript:n + { + mark ~ #1 ~ ( #3 ) /PUT ~ pdfmark ~ + mark ~ #1 ~ << #2 >> /PUT ~ pdfmark + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_object_now:nn, \@@_backend_object_now:ne} +% No anonymous objects, so things are done manually. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_object_now:nn #1#2 + { + \int_gincr:N \g_@@_backend_object_int + \@@_backend_object_write_aux:nnn + { { pdf.obj \int_use:N \g_@@_backend_object_int } } + {#1} {#2} + } +\cs_generate_variant:Nn \@@_backend_object_now:nn { ne } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_backend_object_last:} +% Much like the annotation version. +% \begin{macrocode} +\cs_new:Npn \@@_backend_object_last: + { { pdf.obj \int_use:N \g_@@_backend_object_int } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_backend_pageobject_ref:n} +% Page references are easy in \texttt{dvips}. +% \begin{macrocode} +\cs_new:Npn \@@_backend_pageobject_ref:n #1 + { { Page #1 } } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Annotations} +% +% 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 co-ordinates 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 crated 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@hook + { + \tl_put_right:Nn \@makecol@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 +% the current anchor point actually is: worked out in PostScript. For the +% rectangle version, we have a bit more PostScript: we need two points. +% fitr without rule spec doesn't work, so it falls back to \texttt{/Fit} here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_destination:nn #1#2 + { + \__kernel_backend_postscript:n { pdf.dest.anchor } + \@@_backend_pdfmark:e + { + /View + [ + \str_case:nnF {#2} + { + { xyz } { /XYZ ~ pdf.dest.point ~ null } + { fit } { /Fit } + { fitb } { /FitB } + { fitbh } { /FitBH ~ pdf.dest.y } + { fitbv } { /FitBV ~ pdf.dest.x } + { fith } { /FitH ~ pdf.dest.y } + { fitv } { /FitV ~ pdf.dest.x } + { fitr } { /Fit } + } + { + /XYZ ~ pdf.dest.point ~ \fp_eval:n { (#2) / 100 } + } + ] + /Dest ( \exp_not:n {#1} ) cvn + /DEST + } + } +\cs_new_protected:Npn \@@_backend_destination:nnnn #1#2#3#4 + { + \exp_args:Ne \@@_backend_destination_aux:nnnn + { \dim_eval:n {#2} } {#1} {#3} {#4} + } +\cs_new_protected:Npn \@@_backend_destination_aux:nnnn #1#2#3#4 + { + \vbox_to_zero:n + { + \__kernel_kern:n {#4} + \hbox:n { \__kernel_backend_postscript:n { pdf.save.ll } } + \tex_vss:D + } + \__kernel_kern:n {#1} + \vbox_to_zero:n + { + \__kernel_kern:n { -#3 } + \hbox:n { \__kernel_backend_postscript:n { pdf.save.ur } } + \tex_vss:D + } + \__kernel_kern:n { -#1 } + \@@_backend_pdfmark:n + { + /View + [ + /FitR ~ + pdf.llx ~ pdf.lly ~ pdf.dest2device ~ + pdf.urx ~ pdf.ury ~ pdf.dest2device + ] + /Dest ( #2 ) cvn + /DEST + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsubsection{Structure} +% +% \begin{macro}{\@@_backend_compresslevel:n} +% \begin{macro}{\@@_backend_compress_objects:n} +% Doable for the usual \texttt{ps2pdf} method. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_compresslevel:n #1 + { + \int_compare:nNnT {#1} = 0 + { + \__kernel_backend_literal_postscript:n + { + /setdistillerparams ~ where + { pop << /CompressPages ~ false >> setdistillerparams } + if + } + } + } +\cs_new_protected:Npn \@@_backend_compress_objects:n #1 + { + \bool_if:nF {#1} + { + \__kernel_backend_literal_postscript:n + { + /setdistillerparams ~ where + { pop << /CompressStreams ~ false >> setdistillerparams } + if + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% {\@@_backend_version_major_gset:n, \@@_backend_version_minor_gset:n} +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_version_major_gset:n #1 + { + \cs_gset:Npe \@@_backend_version_major: { \int_eval:n {#1} } + } +\cs_new_protected:Npn \@@_backend_version_minor_gset:n #1 + { + \cs_gset:Npe \@@_backend_version_minor: { \int_eval:n {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_backend_version_major:, \@@_backend_version_minor:} +% Data not available! +% \begin{macrocode} +\cs_new:Npn \@@_backend_version_major: { -1 } +\cs_new:Npn \@@_backend_version_minor: { -1 } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Marked content} +% +% \begin{macro}{\@@_backend_bdc:nn} +% \begin{macro}{\@@_backend_emc:} +% Simple wrappers. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_bdc:nn #1#2 + { \@@_backend_pdfmark:n { /#1 ~ #2 /BDC } } +\cs_new_protected:Npn \@@_backend_emc: + { \@@_backend_pdfmark:n { /EMC } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\LuaTeX{} and \pdfTeX{} backend} +% +% \begin{macrocode} +%<*luatex|pdftex> +% \end{macrocode} +% +% \subsubsection{Annotations} +% +% \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 ~ +% +%<*pdftex> + \tex_pdfannot:D +% + 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 ~ +% +%<*pdftex> + \exp_not:N \tex_pdflastannot:D +% + \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 ~ +% +%<*pdftex> + \tex_pdfstartlink:D +% + attr {#1} + #2 {#3} + } +\cs_new_protected:Npn \@@_backend_link_end: + { +%<*luatex> + \tex_pdfextension:D endlink \scan_stop: +% +%<*pdftex> + \tex_pdfendlink:D +% + } +% \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 ~ +% +%<*pdftex> + \exp_not:N \tex_pdflastlink:D +% + \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 +% +%<*pdftex> + \tex_pdflinkmargin:D +% + \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 +% with the danger of an unterminated keyword. The zoom given here is a +% percentage, but we need to pass it as \emph{per mille}. The rectangle +% version is also easy as everything is build in. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_destination:nn #1#2 + { +%<*luatex> + \tex_pdfextension:D dest ~ +% +%<*pdftex> + \tex_pdfdest:D +% + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + } +\cs_new_protected:Npn \@@_backend_destination:nnnn #1#2#3#4 + { +%<*luatex> + \tex_pdfextension:D dest ~ +% +%<*pdftex> + \tex_pdfdest:D +% + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsubsection{Catalogue entries} +% +% \begin{macro}{\@@_backend_catalog_gput:nn, \@@_backend_info_gput:nn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_catalog_gput:nn #1#2 + { +%<*luatex> + \tex_pdfextension:D catalog +% +%<*pdftex> + \tex_pdfcatalog:D +% + { / #1 ~ #2 } + } +\cs_new_protected:Npn \@@_backend_info_gput:nn #1#2 + { +%<*luatex> + \tex_pdfextension:D info +% +%<*pdftex> + \tex_pdfinfo:D +% + { / #1 ~ #2 } + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Objects} +% +% \begin{variable}{\g_@@_backend_object_prop} +% For tracking objects to allow finalisation. +% \begin{macrocode} +\prop_new:N \g_@@_backend_object_prop +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_backend_object_new:} +% \begin{macro}[EXP]{\@@_backend_object_ref:n, \@@_backend_object_id:n} +% Declaring objects means reserving at the PDF level plus starting +% tracking. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_object_new: + { +%<*luatex> + \tex_pdfextension:D obj ~ +% +%<*pdftex> + \tex_pdfobj:D +% + reserveobjnum ~ + \int_gset:Nn \g_@@_backend_object_int +%<*luatex> + { \tex_pdffeedback:D lastobj } +% +%<*pdftex> + { \tex_pdflastobj:D } +% + } +\cs_new:Npn \@@_backend_object_ref:n #1 { #1 ~ 0 ~ R } +\cs_new:Npn \@@_backend_object_id:n #1 {#1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_object_write:nnn, \@@_backend_object_write:nne} +% \begin{macro}[EXP]{\@@_backend_object_write:nn} +% \begin{macro}[EXP]{\@@_exp_not_i:nn, \@@_exp_not_ii:nn} +% Writing the data needs a little information about the structure of the +% object. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_object_write:nnn #1#2#3 + { +%<*luatex> + \tex_immediate:D \tex_pdfextension:D obj ~ +% +%<*pdftex> + \tex_immediate:D \tex_pdfobj:D +% + useobjnum ~ #1 + \@@_backend_object_write:nn {#2} {#3} + } +\cs_new:Npn \@@_backend_object_write:nn #1#2 + { + \str_case:nn {#1} + { + { array } { { [ ~ \exp_not:n {#2} ~ ] } } + { dict } { { << ~ \exp_not:n {#2} ~ >> } } + { fstream } + { + stream ~ attr ~ { \@@_exp_not_i:nn #2 } ~ + file ~ { \@@_exp_not_ii:nn #2 } + } + { stream } + { + stream ~ attr ~ { \@@_exp_not_i:nn #2 } ~ + { \@@_exp_not_ii:nn #2 } + } + } + } +\cs_generate_variant:Nn \@@_backend_object_write:nnn { nne } +\cs_new:Npn \@@_exp_not_i:nn #1#2 { \exp_not:n {#1} } +\cs_new:Npn \@@_exp_not_ii:nn #1#2 { \exp_not:n {#2} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_object_now:nn, \@@_backend_object_now:ne} +% Much like writing, but direct creation. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_object_now:nn #1#2 + { +%<*luatex> + \tex_immediate:D \tex_pdfextension:D obj ~ +% +%<*pdftex> + \tex_immediate:D \tex_pdfobj:D +% + \@@_backend_object_write:nn {#1} {#2} + } +\cs_generate_variant:Nn \@@_backend_object_now:nn { ne } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_backend_object_last:} +% Much like annotation. +% \begin{macrocode} +\cs_new:Npe \@@_backend_object_last: + { + \exp_not:N \int_value:w +%<*luatex> + \exp_not:N \tex_pdffeedback:D lastobj ~ +% +%<*pdftex> + \exp_not:N \tex_pdflastobj:D +% + \c_space_tl 0 ~ R + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_backend_pageobject_ref:n} +% The usual wrapper situation; the three spaces here are essential. +% \begin{macrocode} +\cs_new:Npe \@@_backend_pageobject_ref:n #1 + { + \exp_not:N \int_value:w +%<*luatex> + \exp_not:N \tex_pdffeedback:D pageref +% +%<*pdftex> + \exp_not:N \tex_pdfpageref:D +% + \c_space_tl #1 \c_space_tl \c_space_tl \c_space_tl 0 ~ R + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Structure} +% +% \begin{macro}{\@@_backend_compresslevel:n} +% \begin{macro}{\@@_backend_compress_objects:n} +% \begin{macro}{\@@_backend_objcompresslevel:n} +% Simply pass data to the engine. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_compresslevel:n #1 + { + \tex_global:D +%<*luatex> + \tex_pdfvariable:D compresslevel +% +%<*pdftex> + \tex_pdfcompresslevel:D +% + \int_value:w \int_eval:n {#1} \scan_stop: + } +\cs_new_protected:Npn \@@_backend_compress_objects:n #1 + { + \bool_if:nTF {#1} + { \@@_backend_objcompresslevel:n { 2 } } + { \@@_backend_objcompresslevel:n { 0 } } + } +\cs_new_protected:Npn \@@_backend_objcompresslevel:n #1 + { + \tex_global:D +%<*luatex> + \tex_pdfvariable:D objcompresslevel +% +%<*pdftex> + \tex_pdfobjcompresslevel:D +% + #1 \scan_stop: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% {\@@_backend_version_major_gset:n, \@@_backend_version_minor_gset:n} +% The availability of the primitive is not universal, so we have to test +% at load time. +% \begin{macrocode} +\cs_new_protected:Npe \@@_backend_version_major_gset:n #1 + { +%<*luatex> + \int_compare:nNnT \tex_luatexversion:D > { 106 } + { + \exp_not:N \tex_global:D \tex_pdfvariable:D majorversion + \exp_not:N \int_eval:n {#1} \scan_stop: + } +% +%<*pdftex> + \cs_if_exist:NT \tex_pdfmajorversion:D + { + \exp_not:N \tex_global:D \tex_pdfmajorversion:D + \exp_not:N \int_eval:n {#1} \scan_stop: + } +% + } +\cs_new_protected:Npn \@@_backend_version_minor_gset:n #1 + { + \tex_global:D +%<*luatex> + \tex_pdfvariable:D minorversion +% +%<*pdftex> + \tex_pdfminorversion:D +% + \int_eval:n {#1} \scan_stop: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_backend_version_major:, \@@_backend_version_minor:} +% As above. +% \begin{macrocode} +\cs_new:Npe \@@_backend_version_major: + { +%<*luatex> + \int_compare:nNnTF \tex_luatexversion:D > { 106 } + { \exp_not:N \tex_the:D \tex_pdfvariable:D majorversion } + { 1 } +% +%<*pdftex> + \cs_if_exist:NTF \tex_pdfmajorversion:D + { \exp_not:N \tex_the:D \tex_pdfmajorversion:D } + { 1 } +% + } +\cs_new:Npn \@@_backend_version_minor: + { + \tex_the:D +%<*luatex> + \tex_pdfvariable:D minorversion +% +%<*pdftex> + \tex_pdfminorversion:D +% + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Marked content} +% +% \begin{macro}{\@@_backend_bdc:nn} +% \begin{macro}{\@@_backend_emc:} +% Simple wrappers. May need refinement: see +% \url{https://chat.stackexchange.com/transcript/message/49970158#49970158}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_bdc:nn #1#2 + { \__kernel_backend_literal_page:n { /#1 ~ #2 ~ BDC } } +\cs_new_protected:Npn \@@_backend_emc: + { \__kernel_backend_literal_page:n { EMC } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \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: used where we can. +% \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} +% +% \subsubsection{Catalogue entries} +% +% \begin{macro}{\@@_backend_catalog_gput:nn, \@@_backend_info_gput:nn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_catalog_gput:nn #1#2 + { \@@_backend:n { put ~ @catalog << /#1 ~ #2 >> } } +\cs_new_protected:Npn \@@_backend_info_gput:nn #1#2 + { \@@_backend:n { docinfo << /#1 ~ #2 >> } } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Objects} +% +% \begin{variable}{\g_@@_backend_object_prop} +% For tracking objects to allow finalisation. +% \begin{macrocode} +\prop_new:N \g_@@_backend_object_prop +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_backend_object_new:} +% \begin{macro}[EXP]{\@@_backend_object_ref:n, \@@_backend_object_id:n} +% Objects are tracked at the macro level, but we don't have to do anything +% at this stage. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_object_new: + { \int_gincr:N \g_@@_backend_object_int } +\cs_new:Npn \@@_backend_object_ref:n #1 { @pdf.obj #1 } +\cs_new_eq:NN \@@_backend_object_id:n \@@_backend_object_ref:n +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_object_write:nnn, \@@_backend_object_write:nne} +% \begin{macro} +% { +% \@@_backend_object_write_array:nn , +% \@@_backend_object_write_dict:nn , +% \@@_backend_object_write_fstream:nn , +% \@@_backend_object_write_stream:nn +% } +% \begin{macro}{\@@_backend_object_write_stream:nnnn} +% This is where we choose the actual type. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_object_write:nnn #1#2#3 + { + \use:c { @@_backend_object_write_ #2 :nn } + { \@@_backend_object_ref:n {#1} } {#3} + } +\cs_generate_variant:Nn \@@_backend_object_write:nnn { nne } +\cs_new_protected:Npn \@@_backend_object_write_array:nn #1#2 + { + \@@_backend:e + { obj ~ #1 ~ [ ~ \exp_not:n {#2} ~ ] } + } +\cs_new_protected:Npn \@@_backend_object_write_dict:nn #1#2 + { + \@@_backend:e + { obj ~ #1 ~ << ~ \exp_not:n {#2} ~ >> } + } +\cs_new_protected:Npn \@@_backend_object_write_fstream:nn #1#2 + { \@@_backend_object_write_stream:nnnn { f } {#1} #2 } +\cs_new_protected:Npn \@@_backend_object_write_stream:nn #1#2 + { \@@_backend_object_write_stream:nnnn { } {#1} #2 } +\cs_new_protected:Npn \@@_backend_object_write_stream:nnnn #1#2#3#4 + { + \@@_backend:e + { + #1 stream ~ #2 ~ + ( \exp_not:n {#4} ) ~ << \exp_not:n {#3} >> + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_backend_object_now:nn, \@@_backend_object_now:ne} +% No anonymous objects with \texttt{dvipdfmx} so we have to give an +% object name. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_object_now:nn #1#2 + { + \int_gincr:N \g_@@_backend_object_int + \exp_args:Nne \use:c { @@_backend_object_write_ #1 :nn } + { @pdf.obj \int_use:N \g_@@_backend_object_int } + {#2} + } +\cs_generate_variant:Nn \@@_backend_object_now:nn { ne } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_object_last:} +% \begin{macrocode} +\cs_new:Npn \@@_backend_object_last: + { @pdf.obj \int_use:N \g_@@_backend_object_int } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_backend_pageobject_ref:n} +% Page references are easy in \texttt{dvipdfmx}/\XeTeX{}. +% \begin{macrocode} +\cs_new:Npn \@@_backend_pageobject_ref:n #1 + { @page #1 } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Annotations} +% +% \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} +% is from Alexander Grahn: the idea is to avoid needing to do any calculations +% in \TeX{} by using the backend data for \texttt{@xpos} and \texttt{@ypos}. +% \texttt{/FitR} without rule spec doesn't work, so it falls back to +% \texttt{/Fit} here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_destination:nn #1#2 + { + \@@_backend:e + { + dest ~ ( \exp_not:n {#1} ) + [ + @thispage + \str_case:nnF {#2} + { + { xyz } { /XYZ ~ @xpos ~ @ypos ~ null } + { fit } { /Fit } + { fitb } { /FitB } + { fitbh } { /FitBH } + { fitbv } { /FitBV ~ @xpos } + { fith } { /FitH ~ @ypos } + { fitv } { /FitV ~ @xpos } + { fitr } { /Fit } + } + { /XYZ ~ @xpos ~ @ypos ~ \fp_eval:n { (#2) / 100 } } + ] + } + } +\cs_new_protected:Npn \@@_backend_destination:nnnn #1#2#3#4 + { + \exp_args:Ne \@@_backend_destination_aux:nnnn + { \dim_eval:n {#2} } {#1} {#3} {#4} + } +\cs_new_protected:Npn \@@_backend_destination_aux:nnnn #1#2#3#4 + { + \vbox_to_zero:n + { + \__kernel_kern:n {#4} + \hbox:n + { + \@@_backend:n { obj ~ @pdf_ #2 _llx ~ @xpos } + \@@_backend:n { obj ~ @pdf_ #2 _lly ~ @ypos } + } + \tex_vss:D + } + \__kernel_kern:n {#1} + \vbox_to_zero:n + { + \__kernel_kern:n { -#3 } + \hbox:n + { + \@@_backend:n + { + dest ~ (#2) + [ + @thispage + /FitR ~ + @pdf_ #2 _llx ~ @pdf_ #2 _lly ~ + @xpos ~ @ypos + ] + } + } + \tex_vss:D + } + \__kernel_kern:n { -#1 } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsubsection{Structure} +% +% \begin{macro}{\@@_backend_compresslevel:n} +% \begin{macro}{\@@_backend_compress_objects:n} +% Pass data to the backend: these are a one-shot. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_compresslevel:n #1 + { \__kernel_backend_literal:e { dvipdfmx:config~z~ \int_eval:n {#1} } } +\cs_new_protected:Npn \@@_backend_compress_objects:n #1 + { + \bool_if:nF {#1} + { \__kernel_backend_literal:n { dvipdfmx:config~C~0x40 } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% {\@@_backend_version_major_gset:n, \@@_backend_version_minor_gset:n} +% We start with the assumption that the default is active. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_version_major_gset:n #1 + { + \cs_gset:Npe \@@_backend_version_major: { \int_eval:n {#1} } + \__kernel_backend_literal:e { pdf:majorversion~ \@@_backend_version_major: } + } +\cs_new_protected:Npn \@@_backend_version_minor_gset:n #1 + { + \cs_gset:Npe \@@_backend_version_minor: { \int_eval:n {#1} } + \__kernel_backend_literal:e { pdf:minorversion~ \@@_backend_version_minor: } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_backend_version_major:, \@@_backend_version_minor:} +% We start with the assumption that the default is active. +% \begin{macrocode} +\cs_new:Npn \@@_backend_version_major: { 1 } +\cs_new:Npn \@@_backend_version_minor: { 5 } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Marked content} +% +% \begin{macro}{\@@_backend_bdc:nn} +% \begin{macro}{\@@_backend_emc:} +% Simple wrappers. May need refinement: see +% \url{https://chat.stackexchange.com/transcript/message/49970158#49970158}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_bdc:nn #1#2 + { \__kernel_backend_literal_page:n { /#1 ~ #2 ~ BDC } } +\cs_new_protected:Npn \@@_backend_emc: + { \__kernel_backend_literal_page:n { EMC } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{\texttt{dvisvgm} backend} +% +% \begin{macrocode} +%<*dvisvgm> +% \end{macrocode} +% +% \subsubsection{Annotations} +% +% \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} +\cs_new_protected:Npn \@@_backend_destination:nn #1#2 { } +\cs_new_protected:Npn \@@_backend_destination:nnnn #1#2#3#4 { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsubsection{Catalogue entries} +% +% \begin{macro}{\@@_backend_catalog_gput:nn, \@@_backend_info_gput:nn} +% No-op. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_catalog_gput:nn #1#2 { } +\cs_new_protected:Npn \@@_backend_info_gput:nn #1#2 { } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Objects} +% +% \begin{macro}{\@@_backend_object_new:} +% \begin{macro}[EXP]{\@@_backend_object_ref:n, \@@_backend_object_id:n} +% \begin{macro}{\@@_backend_object_write:nnn, \@@_backend_object_write:ne} +% \begin{macro}{\@@_backend_object_now:nn, , \@@_backend_object_now:ne} +% \begin{macro}{\@@_backend_object_last:} +% \begin{macro}[EXP]{\@@_backend_pageobject_ref:n} +% All no-ops here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_object_new: { } +\cs_new:Npn \@@_backend_object_ref:n #1 { } +\cs_new:Npn \@@_backend_object_id:n #1 { } +\cs_new_protected:Npn \@@_backend_object_write:nnn #1#2#3 { } +\cs_new_protected:Npn \@@_backend_object_write:nne #1#2#3 { } +\cs_new_protected:Npn \@@_backend_object_now:nn #1#2 { } +\cs_new_protected:Npn \@@_backend_object_now:ne #1#2 { } +\cs_new:Npn \@@_backend_object_last: { } +\cs_new:Npn \@@_backend_pageobject_ref:n #1 { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsubsection{Structure} +% +% \begin{macro}{\@@_backend_compresslevel:n} +% \begin{macro}{\@@_backend_compress_objects:n} +% These are all no-ops. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_compresslevel:n #1 { } +\cs_new_protected:Npn \@@_backend_compress_objects:n #1 { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% {\@@_backend_version_major_gset:n, \@@_backend_version_minor_gset:n} +% Data not available! +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_version_major_gset:n #1 { } +\cs_new_protected:Npn \@@_backend_version_minor_gset:n #1 { } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_backend_version_major:, \@@_backend_version_minor:} +% Data not available! +% \begin{macrocode} +\cs_new:Npn \@@_backend_version_major: { -1 } +\cs_new:Npn \@@_backend_version_minor: { -1 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_backend_bdc:nn} +% \begin{macro}{\@@_backend_emc:} +% More no-ops. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_bdc:nn #1#2 { } +\cs_new_protected:Npn \@@_backend_emc: { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{PDF Page size (media box)} +% +% For setting the media box, the split between backends is somewhat different +% to other areas, thus we approach this separately. The code here assumes a +% recent \LaTeXe{}: that is ensured at the level above. +% +% \begin{macrocode} +%<*dvipdfmx|dvips> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_pagesize_gset:nn} +% This is done as a backend literal, so we deal with it using the shipout +% hook. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_pagesize_gset:nn #1#2 + { + \__kernel_backend_first_shipout:n + { + \__kernel_backend_literal:e + { +%<*dvipdfmx> + pdf:pagesize ~ + width ~ \dim_eval:n {#1} ~ + height ~ \dim_eval:n {#2} +% +%<*dvips> + papersize = \dim_eval:n {#1} , \dim_eval:n {#2} +% + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*luatex|pdftex|xetex> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_pagesize_gset:nn} +% Pass to the primitives. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_pagesize_gset:nn #1#2 + { + \dim_gset:Nn \tex_pagewidth:D {#1} + \dim_gset:Nn \tex_pageheight:D {#2} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dvisvgm> +% \end{macrocode} +% +% \begin{macro}{\@@_backend_pagesize_gset:nn} +% A no-op. +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_pagesize_gset:nn #1#2 { } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex-dev/l3backend/l3backend.ins b/Master/texmf-dist/source/latex-dev/l3backend/l3backend.ins new file mode 100644 index 00000000000..e24c41d2365 --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/l3backend/l3backend.ins @@ -0,0 +1,168 @@ +\iffalse meta-comment + +File l3backend.ins + +Copyright (C) 2019-2024 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. + +----------------------------------------------------------------------- + +Any modification of this file should ensure that the copyright and +license information is placed in the derived files. + +\fi + +\let\jobname\relax +\input docstrip % +\askforoverwritefalse + +\preamble + +Copyright (C) 2019-2024 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. + +\endpreamble +% stop docstrip adding \endinput +\postamble +\endpostamble + +\keepsilent + +\generate + { + \file{l3backend-dvipdfmx.def} + { + \from{l3backend-basics.dtx} {package,dvipdfmx} + \from{l3backend-color.dtx} {package,dvipdfmx} + \from{l3backend-box.dtx} {package,dvipdfmx} + \from{l3backend-draw.dtx} {package,dvipdfmx} + \from{l3backend-graphics.dtx}{package,dvipdfmx} + \from{l3backend-pdf.dtx} {package,dvipdfmx} + \from{l3backend-opacity.dtx} {package,dvipdfmx} + } + } +\generate + { + \file{l3backend-dvips.def} + { + \from{l3backend-basics.dtx} {package,dvips} + \from{l3backend-color.dtx} {package,dvips} + \from{l3backend-box.dtx} {package,dvips} + \from{l3backend-draw.dtx} {package,dvips} + \from{l3backend-graphics.dtx}{package,dvips} + \from{l3backend-pdf.dtx} {package,dvips} + \from{l3backend-opacity.dtx} {package,dvips} + } + \file{l3backend-dvips.pro} + { + \from{l3backend-header.dtx} {header,dvips} + } + } +\generate + { + \file{l3backend-dvisvgm.def} + { + \from{l3backend-basics.dtx} {package,dvisvgm} + \from{l3backend-color.dtx} {package,dvisvgm} + \from{l3backend-box.dtx} {package,dvisvgm} + \from{l3backend-draw.dtx} {package,dvisvgm} + \from{l3backend-graphics.dtx}{package,dvisvgm} + \from{l3backend-pdf.dtx} {package,dvisvgm} + \from{l3backend-opacity.dtx} {package,dvisvgm} + } + } +\generate + { + \file{l3backend-luatex.def} + { + \from{l3backend-basics.dtx} {package,luatex} + \from{l3backend-color.dtx} {package,luatex} + \from{l3backend-box.dtx} {package,luatex} + \from{l3backend-draw.dtx} {package,luatex} + \from{l3backend-graphics.dtx}{package,luatex} + \from{l3backend-pdf.dtx} {package,luatex} + \from{l3backend-opacity.dtx} {package,luatex} + } + } +\generate + { + \file{l3backend-pdftex.def} + { + \from{l3backend-basics.dtx} {package,pdftex} + \from{l3backend-color.dtx} {package,pdftex} + \from{l3backend-box.dtx} {package,pdftex} + \from{l3backend-draw.dtx} {package,pdftex} + \from{l3backend-graphics.dtx}{package,pdftex} + \from{l3backend-pdf.dtx} {package,pdftex} + \from{l3backend-opacity.dtx} {package,pdftex} + } + } +\generate + { + \file{l3backend-xetex.def} + { + \from{l3backend-basics.dtx} {package,xetex} + \from{l3backend-color.dtx} {package,xetex} + \from{l3backend-box.dtx} {package,xetex} + \from{l3backend-draw.dtx} {package,xetex} + \from{l3backend-graphics.dtx}{package,xetex} + \from{l3backend-pdf.dtx} {package,xetex} + \from{l3backend-opacity.dtx} {package,xetex} + } + } + +% Lua code + +\def\MetaPrefix{--} +\preamble + +Copyright (C) 2023,2024 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. + +\endpreamble +\nopostamble +\generate + { + \file{l3backend-luatex.lua} + { + \from{l3backend-color.dtx} {lua} + \from{l3backend-opacity.dtx} {lua} + } + } + +\endbatchfile diff --git a/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvipdfmx.def b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvipdfmx.def new file mode 100644 index 00000000000..a8a54ec2dae --- /dev/null +++ b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvipdfmx.def @@ -0,0 +1,859 @@ +%% +%% This is file `l3backend-dvipdfmx.def', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3backend-basics.dtx (with options: `package,dvipdfmx') +%% l3backend-color.dtx (with options: `package,dvipdfmx') +%% l3backend-box.dtx (with options: `package,dvipdfmx') +%% l3backend-draw.dtx (with options: `package,dvipdfmx') +%% l3backend-graphics.dtx (with options: `package,dvipdfmx') +%% l3backend-pdf.dtx (with options: `package,dvipdfmx') +%% l3backend-opacity.dtx (with options: `package,dvipdfmx') +%% +%% Copyright (C) 2019-2024 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. +%% +%% File: l3backend-basics.dtx +\ProvidesExplFile + {l3backend-dvipdfmx.def}{2024-04-11}{} + {L3 backend support: dvipdfmx} +\cs_if_exist:NTF \__kernel_dependency_version_check:nn + { + \__kernel_dependency_version_check:nn {2023-10-10} + {l3backend-dvipdfmx.def} + } + { + \cs_if_exist_use:cF { @latex@error } { \errmessage } + { + Mismatched~LaTeX~support~files~detected. \MessageBreak + Loading~aborted! + } + { \use:c { @ehd } } + \tex_endinput:D + } +\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} } } +\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 } +\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 } +\cs_new_protected:Npn \__kernel_backend_literal_page:n #1 + { \__kernel_backend_literal:n { pdf:literal~direct~ #1 } } +\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 } } +%% File: l3backend-color.dtx +\cs_new_protected:Npn \__color_backend_select:n #1 + { \__kernel_backend_literal:n { pdf : bc ~ [ #1 ] } } +\cs_new_eq:NN \__color_backend_select_cmyk:n \__color_backend_select:n +\cs_new_eq:NN \__color_backend_select_gray:n \__color_backend_select:n +\cs_new_eq:NN \__color_backend_select_rgb:n \__color_backend_select:n +\cs_new_protected:Npn \__color_backend_reset: + { \__kernel_backend_literal:n { pdf : ec } } +\cs_new_protected:Npn \__color_backend_select_named:n #1 + { + \str_if_eq:nnTF {#1} { Black } + { \__color_backend_select_gray:n { 0 } } + { \msg_error:nnn { color } { unknown-named-color } {#1} } + } +\msg_new:nnn { color } { unknown-named-color } + { Named~color~'#1'~is~not~known. } +\prop_new:N \g__color_backend_colorant_prop +\cs_new:Npe \__color_backend_devicen_colorants:n #1 + { + \exp_not:N \tl_if_blank:nF {#1} + { + \c_space_tl + << ~ + /Colorants ~ + << ~ + \exp_not:N \__color_backend_devicen_colorants:w #1 ~ + \exp_not:N \q_recursion_tail \c_space_tl + \exp_not:N \q_recursion_stop + >> ~ + >> + } + } +\cs_new:Npn \__color_backend_devicen_colorants:w #1 ~ + { + \quark_if_recursion_tail_stop:n {#1} + \prop_if_in:NnT \g__color_backend_colorant_prop {#1} + { + #1 ~ + \prop_item:Nn \g__color_backend_colorant_prop {#1} ~ + } + \__color_backend_devicen_colorants:w + } +\cs_new_protected:Npn \__color_backend_select_separation:nn #1#2 + { \__kernel_backend_literal:e { pdf : bc ~ \pdf_object_ref:n {#1} ~ [ #2 ] } } +\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn +\cs_new_eq:NN \__color_backend_select_iccbased:nn \__color_backend_select_separation:nn +\cs_new_protected:Npn \__color_backend_init_resource:n #1 + { + } +\cs_new_protected:Npn \__color_backend_separation_init:nnnnn #1#2#3#4#5 + { + \pdf_object_unnamed_write:ne { dict } + { + /FunctionType ~ 2 + /Domain ~ [0 ~ 1] + \tl_if_blank:nF {#3} { /Range ~ [#3] } + /C0 ~ [#4] ~ + /C1 ~ [#5] /N ~ 1 + } + \exp_args:Ne \__color_backend_separation_init:nn + { \str_convert_pdfname:n {#1} } {#2} + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new_protected:Npn \__color_backend_separation_init:nn #1#2 + { + \use:e + { + \pdf_object_new:n { color \int_use:N \g__color_model_int } + \pdf_object_write:nnn { color \int_use:N \g__color_model_int } { array } + { /Separation /#1 ~ #2 ~ \pdf_object_ref_last: } + } + \prop_gput:Nne \g__color_backend_colorant_prop { /#1 } + { \pdf_object_ref_last: } + } +\cs_new_protected:Npn \__color_backend_separation_init_CIELAB:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_illuminant_CIELAB_ #1 } + { + \pdf_object_new:n { __color_illuminant_CIELAB_ #1 } + \pdf_object_write:nne { __color_illuminant_CIELAB_ #1 } { array } + { + /Lab ~ + << + /WhitePoint ~ + [ \tl_use:c { c__color_model_whitepoint_CIELAB_ #1 _tl } ] + /Range ~ [ \c__color_model_range_CIELAB_tl ] + >> + } + } + \__color_backend_separation_init:nnnnn + {#2} + { \pdf_object_ref:n { __color_illuminant_CIELAB_ #1 } } + { \c__color_model_range_CIELAB_tl } + { 100 ~ 0 ~ 0 } + {#3} + } +\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3 + { + \pdf_object_unnamed_write:ne { stream } + { + { + /FunctionType ~ 4 ~ + /Domain ~ + [ ~ + \prg_replicate:nn + { 0 \__color_backend_devicen_init:w #1 ~ \s__color_stop } + { 0 ~ 1 ~ } + ] ~ + /Range ~ + [ ~ + \str_case:nn {#2} + { + { /DeviceCMYK } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 } + { /DeviceGray } { 0 ~ 1 } + { /DeviceRGB } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 } + } ~ + ] + } + { {#3} } + } + \use:e + { + \pdf_object_new:n { color \int_use:N \g__color_model_int } + \pdf_object_write:nnn { color \int_use:N \g__color_model_int } { array } + { + /DeviceN ~ + [ ~ #1 ~ ] ~ + #2 ~ + \pdf_object_ref_last: + \__color_backend_devicen_colorants:n {#1} + } + } + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new:Npn \__color_backend_devicen_init:w #1 ~ #2 \s__color_stop + { + + 1 + \tl_if_blank:nF {#2} + { \__color_backend_devicen_init:w #2 \s__color_stop } + } +\cs_new_protected:Npn \__color_backend_iccbased_init:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_icc_ #1 } + { + \pdf_object_new:n { __color_icc_ #1 } + \pdf_object_write:nne { __color_icc_ #1 } { fstream } + { + { + /N ~ \exp_not:n { #2 } ~ + \tl_if_empty:nF { #3 } { /Range~[ #3 ] } + } + {#1} + } + } + \pdf_object_unnamed_write:ne { array } + { /ICCBased ~ \pdf_object_ref:n { __color_icc_ #1 } } + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new_protected:Npn \__color_backend_iccbased_device:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_icc_ #1 } + { + \pdf_object_new:n { __color_icc_ #1 } + \pdf_object_write:nnn { __color_icc_ #1 } { fstream } + { + { /N ~ #3 } + {#1} + } + } + \pdf_object_unnamed_write:ne { array } + { /ICCBased ~ \pdf_object_ref:n { __color_icc_ #1 } } + \__color_backend_init_resource:n { Default #2 } + } +\cs_new_protected:Npn \__color_backend_fill:n #1 + { \__kernel_backend_literal:n { pdf : bc ~ fill ~ [ #1 ] } } +\cs_new_eq:NN \__color_backend_fill_cmyk:n \__color_backend_fill:n +\cs_new_eq:NN \__color_backend_fill_gray:n \__color_backend_fill:n +\cs_new_eq:NN \__color_backend_fill_rgb:n \__color_backend_fill:n +\cs_new_protected:Npn \__color_backend_stroke:n #1 + { \__kernel_backend_literal:n { pdf : bc ~ stroke ~ [ #1 ] } } +\cs_new_eq:NN \__color_backend_stroke_cmyk:n \__color_backend_stroke:n +\cs_new_eq:NN \__color_backend_stroke_gray:n \__color_backend_stroke:n +\cs_new_eq:NN \__color_backend_stroke_rgb:n \__color_backend_stroke:n +\cs_new_protected:Npn \__color_backend_fill_separation:nn #1#2 + { + \__kernel_backend_literal:e + { pdf : bc ~ fill ~ \pdf_object_ref:n {#1} ~ [ #2 ] } + } +\cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2 + { + \__kernel_backend_literal:e + { pdf : bc ~ stroke ~ \pdf_object_ref:n {#1} ~ [ #2 ] } + } +\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn +\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn +\cs_new_eq:NN \__color_backend_fill_reset: \__color_backend_reset: +\cs_new_eq:NN \__color_backend_stroke_reset: \__color_backend_reset: +%% File: l3backend-box.dtx +\cs_new_protected:Npn \__box_backend_clip:N #1 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal_pdf:e + { + 0~ + \dim_to_decimal_in_bp:n { -\box_dp:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~ + re~W~n + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + \skip_horizontal:n { \box_wd:N #1 } + } +\cs_new_protected:Npn \__box_backend_rotate:Nn #1#2 + { \exp_args:NNf \__box_backend_rotate_aux:Nn #1 { \fp_eval:n {#2} } } +\cs_new_protected:Npn \__box_backend_rotate_aux:Nn #1#2 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal:e + { + x:rotate~ + \fp_compare:nNnTF {#2} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( #2 , 5 ) } } + } + \box_use:N #1 + \__kernel_backend_scope_end: + } +\cs_new_protected:Npn \__box_backend_scale:Nnn #1#2#3 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal:e + { + x:scale~ + \fp_eval:n { round ( #2 , 5 ) } ~ + \fp_eval:n { round ( #3 , 5 ) } + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +%% 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_protected:Npn \__draw_backend_begin: + { \__draw_backend_scope_begin: } +\cs_new_protected:Npn \__draw_backend_end: + { \__draw_backend_scope_end: } +\cs_new_eq:NN \__draw_backend_scope_begin: \__kernel_backend_scope_begin: +\cs_new_eq:NN \__draw_backend_scope_end: \__kernel_backend_scope_end: +\cs_new_protected:Npn \__draw_backend_moveto:nn #1#2 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ m } + } +\cs_new_protected:Npn \__draw_backend_lineto:nn #1#2 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ l } + } +\cs_new_protected:Npn \__draw_backend_curveto:nnnnnn #1#2#3#4#5#6 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~ + c + } + } +\cs_new_protected:Npn \__draw_backend_rectangle:nnnn #1#2#3#4 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + re + } + } +\cs_new_protected:Npn \__draw_backend_evenodd_rule: + { \bool_gset_true:N \g__draw_draw_eor_bool } +\cs_new_protected:Npn \__draw_backend_nonzero_rule: + { \bool_gset_false:N \g__draw_draw_eor_bool } +\bool_new:N \g__draw_draw_eor_bool +\cs_new_protected:Npn \__draw_backend_closepath: + { \__draw_backend_literal:n { h } } +\cs_new_protected:Npn \__draw_backend_stroke: + { \__draw_backend_literal:n { S } } +\cs_new_protected:Npn \__draw_backend_closestroke: + { \__draw_backend_literal:n { s } } +\cs_new_protected:Npn \__draw_backend_fill: + { + \__draw_backend_literal:e + { f \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_fillstroke: + { + \__draw_backend_literal:e + { B \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_clip: + { + \__draw_backend_literal:e + { W \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_discardpath: + { \__draw_backend_literal:n { n } } +\cs_new_protected:Npn \__draw_backend_dash_pattern:nn #1#2 + { + \__draw_backend_literal:e + { + [ + \exp_args:Nf \use:n + { \clist_map_function:nN {#1} \__draw_backend_dash:n } + ] ~ + \dim_to_decimal_in_bp:n {#2} ~ d + } + } +\cs_new:Npn \__draw_backend_dash:n #1 + { ~ \dim_to_decimal_in_bp:n {#1} } +\cs_new_protected:Npn \__draw_backend_linewidth:n #1 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ w } + } +\cs_new_protected:Npn \__draw_backend_miterlimit:n #1 + { \__draw_backend_literal:e { #1 ~ M } } +\cs_new_protected:Npn \__draw_backend_cap_butt: + { \__draw_backend_literal:n { 0 ~ J } } +\cs_new_protected:Npn \__draw_backend_cap_round: + { \__draw_backend_literal:n { 1 ~ J } } +\cs_new_protected:Npn \__draw_backend_cap_rectangle: + { \__draw_backend_literal:n { 2 ~ J } } +\cs_new_protected:Npn \__draw_backend_join_miter: + { \__draw_backend_literal:n { 0 ~ j } } +\cs_new_protected:Npn \__draw_backend_join_round: + { \__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 + { + \__draw_backend_cm_decompose:nnnnN {#1} {#2} {#3} {#4} + \__draw_backend_cm_aux:nnnn + } +\cs_new_protected:Npn \__draw_backend_cm_aux:nnnn #1#2#3#4 + { + \__kernel_backend_literal:e + { + x:rotate~ + \fp_compare:nNnTF {#1} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( -#1 , 5 ) } } + } + \__kernel_backend_literal:e + { + x:scale~ + \fp_eval:n { round ( #2 , 5 ) } ~ + \fp_eval:n { round ( #3 , 5 ) } + } + \__kernel_backend_literal:e + { + x:rotate~ + \fp_compare:nNnTF {#4} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( -#4 , 5 ) } } + } + } +\cs_new_protected:Npn \__draw_backend_cm_decompose:nnnnN #1#2#3#4#5 + { + \use:e + { + \__draw_backend_cm_decompose_auxi:nnnnN + { \fp_eval:n { (#1 + #4) / 2 } } + { \fp_eval:n { (#1 - #4) / 2 } } + { \fp_eval:n { (#3 + #2) / 2 } } + { \fp_eval:n { (#3 - #2) / 2 } } + } + #5 + } +\cs_new_protected:Npn \__draw_backend_cm_decompose_auxi:nnnnN #1#2#3#4#5 + { + \use:e + { + \__draw_backend_cm_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 ) } } + { \fp_eval:n { atand ( #4 , #1 ) } } + } + #5 + } +\cs_new_protected:Npn \__draw_backend_cm_decompose_auxii:nnnnN #1#2#3#4#5 + { + \use:e + { + \__draw_backend_cm_decompose_auxiii:nnnnN + { \fp_eval:n { ( #4 - #3 ) / 2 } } + { \fp_eval:n { ( #1 + #2 ) / 2 } } + { \fp_eval:n { ( #1 - #2 ) / 2 } } + { \fp_eval:n { ( #4 + #3 ) / 2 } } + } + #5 + } +\cs_new_protected:Npn \__draw_backend_cm_decompose_auxiii:nnnnN #1#2#3#4#5 + { + \fp_compare:nNnTF { abs( #2 ) } > { abs ( #3 ) } + { #5 {#1} {#2} {#3} {#4} } + { #5 {#1} {#3} {#2} {#4} } + } +\cs_new_protected:Npn \__draw_backend_box_use:Nnnnn #1#2#3#4#5 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal:n + { pdf:btrans~matrix~ #2 ~ #3 ~ #4 ~ #5 ~ 0 ~ 0 } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_literal:n { pdf:etrans } + \__kernel_backend_scope_end: + } +%% File: l3backend-graphics.dtx +\cs_new_protected:Npn \__graphics_backend_loaded:n #1 + { + \cs_if_exist:NTF \hook_gput_code:nnn + { + \hook_gput_code:nnn + { package / l3graphics / after } + { backend } + {#1} + } + {#1} + } +\__graphics_backend_loaded:n + { + \seq_set_from_clist:Nn \l_graphics_search_ext_seq + { .pdf , .eps , .ps , .png , .jpg , .jpeg , .bmp } + } +\__graphics_backend_loaded:n + { + \cs_new_eq:NN \__graphics_backend_getbb_eps:n \__graphics_read_bb:n + \cs_new_eq:NN \__graphics_backend_getbb_ps:n \__graphics_read_bb:n + } +\cs_new_protected:Npn \__graphics_backend_getbb_jpg:n #1 + { + \int_zero:N \l__graphics_page_int + \tl_clear:N \l__graphics_pagebox_tl + \__graphics_extract_bb:n {#1} + } +\cs_new_eq:NN \__graphics_backend_getbb_jpeg:n \__graphics_backend_getbb_jpg:n +\cs_new_eq:NN \__graphics_backend_getbb_png:n \__graphics_backend_getbb_jpg:n +\cs_new_eq:NN \__graphics_backend_getbb_bmp:n \__graphics_backend_getbb_jpg:n +\cs_new_protected:Npn \__graphics_backend_getbb_pdf:n #1 + { + \tl_clear:N \l__graphics_decodearray_str + \bool_set_false:N \l__graphics_interpolate_bool + \__graphics_extract_bb:n {#1} + } +\int_new:N \g__graphics_track_int +\cs_new_protected:Npn \__graphics_backend_include_eps:n #1 + { + \__kernel_backend_literal:e + { + PSfile = #1 \c_space_tl + llx = \dim_to_decimal_in_bp:n \l__graphics_llx_dim \c_space_tl + lly = \dim_to_decimal_in_bp:n \l__graphics_lly_dim \c_space_tl + urx = \dim_to_decimal_in_bp:n \l__graphics_urx_dim \c_space_tl + ury = \dim_to_decimal_in_bp:n \l__graphics_ury_dim + } + } +\cs_new_eq:NN \__graphics_backend_include_ps:n \__graphics_backend_include_eps:n +\cs_new_protected:Npn \__graphics_backend_include_jpg:n #1 + { \__graphics_backend_include_auxi:nn {#1} { image } } +\cs_new_eq:NN \__graphics_backend_include_jpeg:n \__graphics_backend_include_jpg:n +\cs_new_eq:NN \__graphics_backend_include_png:n \__graphics_backend_include_jpg:n +\cs_new_eq:NN \__graphics_backend_include_bmp:n \__graphics_backend_include_jpg:n +\cs_new_protected:Npn \__graphics_backend_include_pdf:n #1 + { \__graphics_backend_include_auxi:nn {#1} { epdf } } +\cs_new_protected:Npn \__graphics_backend_include_auxi:nn #1#2 + { + \__graphics_backend_include_auxii:enn + { + \tl_if_empty:NF \l__graphics_pagebox_tl + { : \l__graphics_pagebox_tl } + \int_compare:nNnT \l__graphics_page_int > 1 + { :P \int_use:N \l__graphics_page_int } + \tl_if_empty:NF \l__graphics_decodearray_str + { :D \l__graphics_decodearray_str } + \bool_if:NT \l__graphics_interpolate_bool + { :I } + } + {#1} {#2} + } +\cs_new_protected:Npn \__graphics_backend_include_auxii:nnn #1#2#3 + { + \int_if_exist:cTF { c__graphics_ #2#1 _int } + { + \__kernel_backend_literal:e + { pdf:usexobj~@graphic \int_use:c { c__graphics_ #2#1 _int } } + } + { \__graphics_backend_include_auxiii:nnn {#2} {#1} {#3} } + } +\cs_generate_variant:Nn \__graphics_backend_include_auxii:nnn { e } +\cs_new_protected:Npn \__graphics_backend_include_auxiii:nnn #1#2#3 + { + \int_gincr:N \g__graphics_track_int + \int_const:cn { c__graphics_ #1#2 _int } { \g__graphics_track_int } + \__kernel_backend_literal:e + { + pdf:#3~ + @graphic \int_use:c { c__graphics_ #1#2 _int } ~ + \int_compare:nNnT \l__graphics_page_int > 1 + { page ~ \int_use:N \l__graphics_page_int \c_space_tl } + \tl_if_empty:NF \l__graphics_pagebox_tl + { + pagebox ~ \l__graphics_pagebox_tl \c_space_tl + bbox ~ + \dim_to_decimal_in_bp:n \l__graphics_llx_dim \c_space_tl + \dim_to_decimal_in_bp:n \l__graphics_lly_dim \c_space_tl + \dim_to_decimal_in_bp:n \l__graphics_urx_dim \c_space_tl + \dim_to_decimal_in_bp:n \l__graphics_ury_dim \c_space_tl + } + (#1) + \bool_lazy_or:nnT + { \l__graphics_interpolate_bool } + { ! \tl_if_empty_p:N \l__graphics_decodearray_str } + { + << + \tl_if_empty:NF \l__graphics_decodearray_str + { /Decode~[ \l__graphics_decodearray_str ] } + \bool_if:NT \l__graphics_interpolate_bool + { /Interpolate~true } + >> + } + } + } +\__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 } +\cs_new_protected:Npn \__pdf_backend_catalog_gput:nn #1#2 + { \__pdf_backend:n { put ~ @catalog << /#1 ~ #2 >> } } +\cs_new_protected:Npn \__pdf_backend_info_gput:nn #1#2 + { \__pdf_backend:n { docinfo << /#1 ~ #2 >> } } +\prop_new:N \g__pdf_backend_object_prop +\cs_new_protected:Npn \__pdf_backend_object_new: + { \int_gincr:N \g__pdf_backend_object_int } +\cs_new:Npn \__pdf_backend_object_ref:n #1 { @pdf.obj #1 } +\cs_new_eq:NN \__pdf_backend_object_id:n \__pdf_backend_object_ref:n +\cs_new_protected:Npn \__pdf_backend_object_write:nnn #1#2#3 + { + \use:c { __pdf_backend_object_write_ #2 :nn } + { \__pdf_backend_object_ref:n {#1} } {#3} + } +\cs_generate_variant:Nn \__pdf_backend_object_write:nnn { nne } +\cs_new_protected:Npn \__pdf_backend_object_write_array:nn #1#2 + { + \__pdf_backend:e + { obj ~ #1 ~ [ ~ \exp_not:n {#2} ~ ] } + } +\cs_new_protected:Npn \__pdf_backend_object_write_dict:nn #1#2 + { + \__pdf_backend:e + { obj ~ #1 ~ << ~ \exp_not:n {#2} ~ >> } + } +\cs_new_protected:Npn \__pdf_backend_object_write_fstream:nn #1#2 + { \__pdf_backend_object_write_stream:nnnn { f } {#1} #2 } +\cs_new_protected:Npn \__pdf_backend_object_write_stream:nn #1#2 + { \__pdf_backend_object_write_stream:nnnn { } {#1} #2 } +\cs_new_protected:Npn \__pdf_backend_object_write_stream:nnnn #1#2#3#4 + { + \__pdf_backend:e + { + #1 stream ~ #2 ~ + ( \exp_not:n {#4} ) ~ << \exp_not:n {#3} >> + } + } +\cs_new_protected:Npn \__pdf_backend_object_now:nn #1#2 + { + \int_gincr:N \g__pdf_backend_object_int + \exp_args:Nne \use:c { __pdf_backend_object_write_ #1 :nn } + { @pdf.obj \int_use:N \g__pdf_backend_object_int } + {#2} + } +\cs_generate_variant:Nn \__pdf_backend_object_now:nn { ne } +\cs_new:Npn \__pdf_backend_object_last: + { @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 + { + dest ~ ( \exp_not:n {#1} ) + [ + @thispage + \str_case:nnF {#2} + { + { xyz } { /XYZ ~ @xpos ~ @ypos ~ null } + { fit } { /Fit } + { fitb } { /FitB } + { fitbh } { /FitBH } + { fitbv } { /FitBV ~ @xpos } + { fith } { /FitH ~ @ypos } + { fitv } { /FitV ~ @xpos } + { fitr } { /Fit } + } + { /XYZ ~ @xpos ~ @ypos ~ \fp_eval:n { (#2) / 100 } } + ] + } + } +\cs_new_protected:Npn \__pdf_backend_destination:nnnn #1#2#3#4 + { + \exp_args:Ne \__pdf_backend_destination_aux:nnnn + { \dim_eval:n {#2} } {#1} {#3} {#4} + } +\cs_new_protected:Npn \__pdf_backend_destination_aux:nnnn #1#2#3#4 + { + \vbox_to_zero:n + { + \__kernel_kern:n {#4} + \hbox:n + { + \__pdf_backend:n { obj ~ @pdf_ #2 _llx ~ @xpos } + \__pdf_backend:n { obj ~ @pdf_ #2 _lly ~ @ypos } + } + \tex_vss:D + } + \__kernel_kern:n {#1} + \vbox_to_zero:n + { + \__kernel_kern:n { -#3 } + \hbox:n + { + \__pdf_backend:n + { + dest ~ (#2) + [ + @thispage + /FitR ~ + @pdf_ #2 _llx ~ @pdf_ #2 _lly ~ + @xpos ~ @ypos + ] + } + } + \tex_vss:D + } + \__kernel_kern:n { -#1 } + } +\cs_new_protected:Npn \__pdf_backend_compresslevel:n #1 + { \__kernel_backend_literal:e { dvipdfmx:config~z~ \int_eval:n {#1} } } +\cs_new_protected:Npn \__pdf_backend_compress_objects:n #1 + { + \bool_if:nF {#1} + { \__kernel_backend_literal:n { dvipdfmx:config~C~0x40 } } + } +\cs_new_protected:Npn \__pdf_backend_version_major_gset:n #1 + { + \cs_gset:Npe \__pdf_backend_version_major: { \int_eval:n {#1} } + \__kernel_backend_literal:e { pdf:majorversion~ \__pdf_backend_version_major: } + } +\cs_new_protected:Npn \__pdf_backend_version_minor_gset:n #1 + { + \cs_gset:Npe \__pdf_backend_version_minor: { \int_eval:n {#1} } + \__kernel_backend_literal:e { pdf:minorversion~ \__pdf_backend_version_minor: } + } +\cs_new:Npn \__pdf_backend_version_major: { 1 } +\cs_new:Npn \__pdf_backend_version_minor: { 5 } +\cs_new_protected:Npn \__pdf_backend_bdc:nn #1#2 + { \__kernel_backend_literal_page:n { /#1 ~ #2 ~ BDC } } +\cs_new_protected:Npn \__pdf_backend_emc: + { \__kernel_backend_literal_page:n { EMC } } +\cs_new_protected:Npn \__pdf_backend_pagesize_gset:nn #1#2 + { + \__kernel_backend_first_shipout:n + { + \__kernel_backend_literal:e + { + pdf:pagesize ~ + width ~ \dim_eval:n {#1} ~ + height ~ \dim_eval:n {#2} + } + } + } +%% File: l3backend-opacity.dtx +\bool_lazy_and:nnT + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity 1 } { << /ca ~ 1 /CA ~ 1 >> } + } +\tl_new:N \l__opacity_backend_fill_tl +\tl_new:N \l__opacity_backend_stroke_tl +\tl_set:Nn \l__opacity_backend_fill_tl { 1 } +\tl_set:Nn \l__opacity_backend_stroke_tl { 1 } +\cs_new_protected:Npn \__opacity_backend_select:n #1 + { + \tl_set:Nn \l__opacity_backend_fill_tl {#1} + \tl_set:Nn \l__opacity_backend_stroke_tl {#1} + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity #1 } + { << /ca ~ #1 /CA ~ #1 >> } + \__kernel_backend_literal_pdf:n + { /opacity #1 ~ gs } + \group_insert_after:N \__opacity_backend_reset: + } +\cs_new_protected:Npn \__opacity_backend_reset: + { + \__kernel_backend_literal_pdf:n + { /opacity1 ~ gs } + } +\cs_new_protected:Npn \__opacity_backend_fill:n #1 + { + \exp_args:Nno \__opacity_backend_fill_stroke:nn + { #1 } + { \l__opacity_backend_stroke_tl } + } +\cs_new_protected:Npn \__opacity_backend_stroke:n #1 + { + \exp_args:No \__opacity_backend_fill_stroke:nn + { \l__opacity_backend_fill_tl } + { #1 } + } +\cs_new_protected:Npn \__opacity_backend_fill_stroke:nn #1#2 + { + \str_if_eq:nnTF {#1} {#2} + { \__opacity_backend_select:n {#1} } + { + \tl_set:Nn \l__opacity_backend_fill_tl {#1} + \tl_set:Nn \l__opacity_backend_stroke_tl {#2} + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity.fill #1 } + { << /ca ~ #1 >> } + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity.stroke #2 } + { << /CA ~ #2 >> } + \__kernel_backend_literal_pdf:n + { /opacity.fill #1 ~ gs /opacity.stroke #2 ~ gs } + \group_insert_after:N \__opacity_backend_reset: + } + } +\bool_lazy_and:nnF + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \cs_gset_protected:Npn \__opacity_backend_select:n #1 { } + \cs_gset_protected:Npn \__opacity_backend_fill_stroke:nn #1#2 { } + } +%% +%% +%% End of file `l3backend-dvipdfmx.def'. diff --git a/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.def b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.def new file mode 100644 index 00000000000..0c60ac3e936 --- /dev/null +++ b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.def @@ -0,0 +1,1064 @@ +%% +%% This is file `l3backend-dvips.def', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3backend-basics.dtx (with options: `package,dvips') +%% l3backend-color.dtx (with options: `package,dvips') +%% l3backend-box.dtx (with options: `package,dvips') +%% l3backend-draw.dtx (with options: `package,dvips') +%% l3backend-graphics.dtx (with options: `package,dvips') +%% l3backend-pdf.dtx (with options: `package,dvips') +%% l3backend-opacity.dtx (with options: `package,dvips') +%% +%% Copyright (C) 2019-2024 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. +%% +%% File: l3backend-basics.dtx +\ProvidesExplFile + {l3backend-dvips.def}{2024-04-11}{} + {L3 backend support: dvips} +\cs_if_exist:NTF \__kernel_dependency_version_check:nn + { + \__kernel_dependency_version_check:nn {2023-10-10} + {l3backend-dvips.def} + } + { + \cs_if_exist_use:cF { @latex@error } { \errmessage } + { + Mismatched~LaTeX~support~files~detected. \MessageBreak + Loading~aborted! + } + { \use:c { @ehd } } + \tex_endinput:D + } +\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} } } +\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 } +\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 } +\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 } +\bool_if:NT \g__kernel_backend_header_bool + { + \__kernel_backend_first_shipout:n + { \__kernel_backend_literal:n { header = l3backend-dvips.pro } } + } +\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] } + } +\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 } } +%% File: l3backend-color.dtx +\cs_new_protected:Npn \__color_backend_select_cmyk:n #1 + { \__color_backend_select:n { cmyk ~ #1 } } +\cs_new_protected:Npn \__color_backend_select_gray:n #1 + { \__color_backend_select:n { gray ~ #1 } } +\cs_new_protected:Npn \__color_backend_select_named:n #1 + { \__color_backend_select:n { ~ #1 } } +\cs_new_protected:Npn \__color_backend_select_rgb:n #1 + { \__color_backend_select:n { rgb ~ #1 } } +\cs_new_protected:Npn \__color_backend_select:n #1 + { + \__kernel_backend_literal:n { color~push~ #1 } + \__kernel_backend_postscript:n { /color.sc ~ { } ~ def } + } +\cs_new_protected:Npn \__color_backend_reset: + { \__kernel_backend_literal:n { color~pop } } +\prop_new:N \g__color_backend_colorant_prop +\cs_new:Npe \__color_backend_devicen_colorants:n #1 + { + \exp_not:N \tl_if_blank:nF {#1} + { + \c_space_tl + << ~ + /Colorants ~ + << ~ + \exp_not:N \__color_backend_devicen_colorants:w #1 ~ + \exp_not:N \q_recursion_tail \c_space_tl + \exp_not:N \q_recursion_stop + >> ~ + >> + } + } +\cs_new:Npn \__color_backend_devicen_colorants:w #1 ~ + { + \quark_if_recursion_tail_stop:n {#1} + \prop_if_in:NnT \g__color_backend_colorant_prop {#1} + { + #1 ~ + \prop_item:Nn \g__color_backend_colorant_prop {#1} ~ + } + \__color_backend_devicen_colorants:w + } +\cs_new_protected:Npn \__color_backend_select_separation:nn #1#2 + { \__color_backend_select:n { separation ~ #1 ~ #2 } } +\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn +\cs_new_protected:Npn \__color_backend_select_iccbased:nn #1#2 { } +\cs_new_protected:Npe \__color_backend_separation_init:nnnnn #1#2#3#4#5 + { + \bool_if:NT \g__kernel_backend_header_bool + { + \exp_not:N \exp_args:Ne \__kernel_backend_first_shipout:n + { + \exp_not:N \__color_backend_separation_init_aux:nnnnnn + { \exp_not:N \int_use:N \g__color_model_int } + {#1} {#2} {#3} {#4} {#5} + } + \prop_gput:Nee \exp_not:N \g__color_backend_colorant_prop + { / \exp_not:N \str_convert_pdfname:n {#1} } + { + << ~ + /setcolorspace ~ {} ~ + >> ~ begin ~ + color \exp_not:N \int_use:N \g__color_model_int \c_space_tl + end + } + } + } +\cs_generate_variant:Nn \__color_backend_separation_init:nnnnn { nee } +\cs_new_protected:Npn \__color_backend_separation_init_aux:nnnnnn #1#2#3#4#5#6 + { + \__kernel_backend_literal:e + { + ! + TeXDict ~ begin ~ + /color #1 + { + [ ~ + /Separation ~ ( \str_convert_pdfname:n {#2} ) ~ + [ ~ #3 ~ ] ~ + { + \cs_if_exist_use:cF { __color_backend_separation_init_ #3 :nnn } + { \__color_backend_separation_init:nnn } + {#4} {#5} {#6} + } + ] ~ setcolorspace + } ~ def ~ + end + } + } +\cs_new:cpn { __color_backend_separation_init_ /DeviceCMYK :nnn } #1#2#3 + { \__color_backend_separation_init_Device:Nn 4 {#3} } +\cs_new:cpn { __color_backend_separation_init_ /DeviceGray :nnn } #1#2#3 + { \__color_backend_separation_init_Device:Nn 1 {#3} } +\cs_new:cpn { __color_backend_separation_init_ /DeviceRGB :nnn } #1#2#3 + { \__color_backend_separation_init_Device:Nn 2 {#3} } +\cs_new:Npn \__color_backend_separation_init_Device:Nn #1#2 + { + #2 ~ + \prg_replicate:nn {#1} + { #1 ~ index ~ mul ~ #1 ~ 1 ~ roll ~ } + \int_eval:n { #1 + 1 } ~ -1 ~ roll ~ pop + } +\cs_new:Npn \__color_backend_separation_init:nnn #1#2#3 + { + \exp_args:Ne \__color_backend_separation_init:nnnn + { \__color_backend_separation_init_count:n {#2} } + {#1} {#2} {#3} + } +\cs_new:Npn \__color_backend_separation_init_count:n #1 + { \int_eval:n { 0 \__color_backend_separation_init_count:w #1 ~ \s__color_stop } } +\cs_new:Npn \__color_backend_separation_init_count:w #1 ~ #2 \s__color_stop + { + +1 + \tl_if_blank:nF {#2} + { \__color_backend_separation_init_count:w #2 \s__color_stop } + } +\cs_new:Npn \__color_backend_separation_init:nnnn #1#2#3#4 + { + \__color_backend_separation_init:w #3 ~ \s__color_stop #4 ~ \s__color_stop + \prg_replicate:nn {#1} + { + pop ~ 1 ~ index ~ neg ~ 1 ~ index ~ add ~ + \int_eval:n { 3 * #1 } ~ index ~ mul ~ + 2 ~ index ~ add ~ + \int_eval:n { 3 * #1 } ~ #1 ~ roll ~ + } + \int_step_function:nnnN {#1} { -1 } { 1 } + \__color_backend_separation_init:n + \int_eval:n { 4 * #1 + 1 } ~ #1 ~ roll ~ + \prg_replicate:nn { 3 * #1 + 1 } { pop ~ } + \tl_if_blank:nF {#2} + { \__color_backend_separation_init:nw {#1} #2 ~ \s__color_stop } + } +\cs_new:Npn \__color_backend_separation_init:w + #1 ~ #2 \s__color_stop #3 ~ #4 \s__color_stop + { + #1 ~ #3 ~ 0 ~ + \tl_if_blank:nF {#2} + { \__color_backend_separation_init:w #2 \s__color_stop #4 \s__color_stop } + } +\cs_new:Npn \__color_backend_separation_init:n #1 + { \int_eval:n { #1 * 2 } ~ index ~ } +\cs_new:Npn \__color_backend_separation_init:nw #1#2 ~ #3 ~ #4 \s__color_stop + { + #2 ~ #3 ~ + 2 ~ index ~ 2 ~ index ~ lt ~ + { ~ pop ~ exch ~ pop ~ } ~ + { ~ + 2 ~ index ~ 1 ~ index ~ gt ~ + { ~ exch ~ pop ~ exch ~ pop ~ } ~ + { ~ pop ~ pop ~ } ~ + ifelse ~ + } + ifelse ~ + #1 ~ 1 ~ roll ~ + \tl_if_blank:nF {#4} + { \__color_backend_separation_init:nw {#1} #4 \s__color_stop } + } +\cs_new_protected:Npn \__color_backend_separation_init_CIELAB:nnn #1#2#3 + { + \__color_backend_separation_init:neenn + {#2} + { + /CIEBasedABC ~ + << ~ + /RangeABC ~ [ ~ \c__color_model_range_CIELAB_tl \c_space_tl ] ~ + /DecodeABC ~ + [ ~ + { ~ 16 ~ add ~ 116 ~ div ~ } ~ bind ~ + { ~ 500 ~ div ~ } ~ bind ~ + { ~ 200 ~ div ~ } ~ bind ~ + ] ~ + /MatrixABC ~ [ ~ 1 ~ 1 ~ 1 ~ 1 ~ 0 ~ 0 ~ 0 ~ 0 ~ -1 ~ ] ~ + /DecodeLMN ~ + [ ~ + { ~ + dup ~ 6 ~ 29 ~ div ~ ge ~ + { ~ dup ~ dup ~ mul ~ mul ~ ~ } ~ + { ~ 4 ~ 29 ~ div ~ sub ~ 108 ~ 841 ~ div ~ mul ~ } ~ + ifelse ~ + 0.9505 ~ mul ~ + } ~ bind ~ + { ~ + dup ~ 6 ~ 29 ~ div ~ ge ~ + { ~ dup ~ dup ~ mul ~ mul ~ } ~ + { ~ 4 ~ 29 ~ div ~ sub ~ 108 ~ 841 ~ div ~ mul ~ } ~ + ifelse ~ + } ~ bind ~ + { ~ + dup ~ 6 ~ 29 ~ div ~ ge ~ + { ~ dup ~ dup ~ mul ~ mul ~ } ~ + { ~ 4 ~ 29 ~ div ~ sub ~ 108 ~ 841 ~ div ~ mul ~ } ~ + ifelse ~ + 1.0890 ~ mul ~ + } ~ bind + ] ~ + /WhitePoint ~ + [ ~ \tl_use:c { c__color_model_whitepoint_CIELAB_ #1 _tl } ~ ] ~ + >> + } + { \c__color_model_range_CIELAB_tl } + { 100 ~ 0 ~ 0 } + {#3} + } +\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3 + { + \__kernel_backend_literal:e + { + ! + TeXDict ~ begin ~ + /color \int_use:N \g__color_model_int + { + [ ~ + /DeviceN ~ + [ ~ #1 ~ ] ~ + #2 ~ + { ~ #3 ~ } ~ + \__color_backend_devicen_colorants:n {#1} + ] ~ setcolorspace + } ~ def ~ + end + } + } +\cs_new_protected:Npn \__color_backend_iccbased_init:nnn #1#2#3 { } +\cs_new_protected:Npn \__color_backend_fill_cmyk:n #1 + { \__color_backend_fill:n { cmyk ~ #1 } } +\cs_new_protected:Npn \__color_backend_fill_gray:n #1 + { \__color_backend_fill:n { gray ~ #1 } } +\cs_new_protected:Npn \__color_backend_fill_rgb:n #1 + { \__color_backend_fill:n { rgb ~ #1 } } +\cs_new_protected:Npn \__color_backend_fill:n #1 + { + \__kernel_backend_literal:n { color~push~ #1 } + } +\cs_new_protected:Npn \__color_backend_stroke_cmyk:n #1 + { \__kernel_backend_postscript:n { /color.sc { #1 ~ setcmykcolor } def } } +\cs_new_protected:Npn \__color_backend_stroke_gray:n #1 + { \__kernel_backend_postscript:n { /color.sc { #1 ~ setgray } def } } +\cs_new_protected:Npn \__color_backend_stroke_rgb:n #1 + { \__kernel_backend_postscript:n { /color.sc { #1 ~ setrgbcolor } def } } +\cs_new_protected:Npn \__color_backend_fill_separation:nn #1#2 + { \__color_backend_fill:n { separation ~ #1 ~ #2 } } +\cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2 + { \__kernel_backend_postscript:n { /color.sc { separation ~ #1 ~ #2 } def } } +\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn +\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn +\cs_new_eq:NN \__color_backend_fill_reset: \__color_backend_reset: +\cs_new_protected:Npn \__color_backend_stroke_reset: { } +%% File: l3backend-box.dtx +\cs_new_protected:Npn \__box_backend_clip:N #1 + { + \__kernel_backend_scope_begin: + \__kernel_backend_align_begin: + \__kernel_backend_literal_postscript:n { matrix~currentmatrix } + \__kernel_backend_literal_postscript:n + { Resolution~72~div~VResolution~72~div~scale } + \__kernel_backend_literal_postscript:n { DVImag~dup~scale } + \__kernel_backend_literal_postscript:e + { + 0 ~ + \dim_to_decimal_in_bp:n { \box_dp:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ + \dim_to_decimal_in_bp:n { -\box_ht:N #1 - \box_dp:N #1 } ~ + rectclip + } + \__kernel_backend_literal_postscript:n { setmatrix } + \__kernel_backend_align_end: + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + \skip_horizontal:n { \box_wd:N #1 } + } +\cs_new_protected:Npn \__box_backend_rotate:Nn #1#2 + { \exp_args:NNf \__box_backend_rotate_aux:Nn #1 { \fp_eval:n {#2} } } +\cs_new_protected:Npn \__box_backend_rotate_aux:Nn #1#2 + { + \__kernel_backend_scope_begin: + \__kernel_backend_align_begin: + \__kernel_backend_literal_postscript:e + { + \fp_compare:nNnTF {#2} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( -(#2) , 5 ) } } ~ + rotate + } + \__kernel_backend_align_end: + \box_use:N #1 + \__kernel_backend_scope_end: + } +\cs_new_protected:Npn \__box_backend_scale:Nnn #1#2#3 + { + \__kernel_backend_scope_begin: + \__kernel_backend_align_begin: + \__kernel_backend_literal_postscript:e + { + \fp_eval:n { round ( #2 , 5 ) } ~ + \fp_eval:n { round ( #3 , 5 ) } ~ + scale + } + \__kernel_backend_align_end: + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +%% File: l3backend-draw.dtx +\cs_new_eq:NN \__draw_backend_literal:n \__kernel_backend_literal_postscript:n +\cs_generate_variant:Nn \__draw_backend_literal:n { e } +\cs_new_protected:Npn \__draw_backend_begin: + { + \__draw_backend_literal:n { [begin] } + \__draw_backend_literal:n { /draw.x~currentpoint~/draw.y~exch~def~def } + \__draw_backend_literal:n { @beginspecial } + } +\cs_new_protected:Npn \__draw_backend_end: + { + \__draw_backend_literal:n { @endspecial } + \__draw_backend_literal:n { [end] } + } +\cs_new_protected:Npn \__draw_backend_scope_begin: + { \__draw_backend_literal:n { save } } +\cs_new_protected:Npn \__draw_backend_scope_end: + { \__draw_backend_literal:n { restore } } +\cs_new_protected:Npn \__draw_backend_moveto:nn #1#2 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ + \dim_to_decimal_in_bp:n {#2} ~ moveto + } + } +\cs_new_protected:Npn \__draw_backend_lineto:nn #1#2 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ + \dim_to_decimal_in_bp:n {#2} ~ lineto + } + } +\cs_new_protected:Npn \__draw_backend_rectangle:nnnn #1#2#3#4 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#4} ~ \dim_to_decimal_in_bp:n {#3} ~ + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + moveto~dup~0~rlineto~exch~0~exch~rlineto~neg~0~rlineto~closepath + } + } +\cs_new_protected:Npn \__draw_backend_curveto:nnnnnn #1#2#3#4#5#6 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~ + curveto + } + } +\cs_new_protected:Npn \__draw_backend_evenodd_rule: + { \bool_gset_true:N \g__draw_draw_eor_bool } +\cs_new_protected:Npn \__draw_backend_nonzero_rule: + { \bool_gset_false:N \g__draw_draw_eor_bool } +\bool_new:N \g__draw_draw_eor_bool +\cs_new_protected:Npn \__draw_backend_closepath: + { \__draw_backend_literal:n { closepath } } +\cs_new_protected:Npn \__draw_backend_stroke: + { + \__draw_backend_literal:n { gsave } + \__draw_backend_literal:n { color.sc } + \__draw_backend_literal:n { stroke } + \__draw_backend_literal:n { grestore } + \bool_if:NT \g__draw_draw_clip_bool + { + \__draw_backend_literal:e + { + \bool_if:NT \g__draw_draw_eor_bool { eo } + clip + } + } + \__draw_backend_literal:n { newpath } + \bool_gset_false:N \g__draw_draw_clip_bool + } +\cs_new_protected:Npn \__draw_backend_closestroke: + { + \__draw_backend_closepath: + \__draw_backend_stroke: + } +\cs_new_protected:Npn \__draw_backend_fill: + { + \__draw_backend_literal:e + { + \bool_if:NT \g__draw_draw_eor_bool { eo } + fill + } + \bool_if:NT \g__draw_draw_clip_bool + { + \__draw_backend_literal:e + { + \bool_if:NT \g__draw_draw_eor_bool { eo } + clip + } + } + \__draw_backend_literal:n { newpath } + \bool_gset_false:N \g__draw_draw_clip_bool + } +\cs_new_protected:Npn \__draw_backend_fillstroke: + { + \__draw_backend_literal:e + { + \bool_if:NT \g__draw_draw_eor_bool { eo } + fill + } + \__draw_backend_literal:n { gsave } + \__draw_backend_literal:n { color.sc } + \__draw_backend_literal:n { stroke } + \__draw_backend_literal:n { grestore } + \bool_if:NT \g__draw_draw_clip_bool + { + \__draw_backend_literal:e + { + \bool_if:NT \g__draw_draw_eor_bool { eo } + clip + } + } + \__draw_backend_literal:n { newpath } + \bool_gset_false:N \g__draw_draw_clip_bool + } +\cs_new_protected:Npn \__draw_backend_clip: + { \bool_gset_true:N \g__draw_draw_clip_bool } +\bool_new:N \g__draw_draw_clip_bool +\cs_new_protected:Npn \__draw_backend_discardpath: + { + \bool_if:NT \g__draw_draw_clip_bool + { + \__draw_backend_literal:e + { + \bool_if:NT \g__draw_draw_eor_bool { eo } + clip + } + } + \__draw_backend_literal:n { newpath } + \bool_gset_false:N \g__draw_draw_clip_bool + } +\cs_new_protected:Npn \__draw_backend_dash_pattern:nn #1#2 + { + \__draw_backend_literal:e + { + [ + \exp_args:Nf \use:n + { \clist_map_function:nN {#1} \__draw_backend_dash:n } + ] ~ + \dim_to_decimal_in_bp:n {#2} ~ setdash + } + } +\cs_new:Npn \__draw_backend_dash:n #1 + { ~ \dim_to_decimal_in_bp:n {#1} } +\cs_new_protected:Npn \__draw_backend_linewidth:n #1 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ setlinewidth } + } +\cs_new_protected:Npn \__draw_backend_miterlimit:n #1 + { \__draw_backend_literal:n { #1 ~ setmiterlimit } } +\cs_new_protected:Npn \__draw_backend_cap_butt: + { \__draw_backend_literal:n { 0 ~ setlinecap } } +\cs_new_protected:Npn \__draw_backend_cap_round: + { \__draw_backend_literal:n { 1 ~ setlinecap } } +\cs_new_protected:Npn \__draw_backend_cap_rectangle: + { \__draw_backend_literal:n { 2 ~ setlinecap } } +\cs_new_protected:Npn \__draw_backend_join_miter: + { \__draw_backend_literal:n { 0 ~ setlinejoin } } +\cs_new_protected:Npn \__draw_backend_join_round: + { \__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 + { + \__draw_backend_literal:n + { [ #1 ~ #2 ~ #3 ~ #4 ~ 0 ~ 0 ] ~ concat } + } +\cs_new_protected:Npn \__draw_backend_box_use:Nnnnn #1#2#3#4#5 + { + \__draw_backend_literal:n { save } + \__draw_backend_literal:n { 72~Resolution~div~72~VResolution~div~neg~scale } + \__draw_backend_literal:n { magscale { 1~DVImag~div~dup~scale } if } + \__draw_backend_literal:n { draw.x~neg~draw.y~neg~translate } + \__draw_backend_literal:n { [end] } + \__draw_backend_literal:n { [begin] } + \__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_literal:n { neg~exch~neg~exch~translate } + \__draw_backend_literal:n { [end] } + \hbox_overlap_right:n { \box_use:N #1 } + \__draw_backend_literal:n { [begin] } + \__draw_backend_literal:n { restore } + \__draw_backend_literal:n { [end] } + \__draw_backend_literal:n { [begin] } + \__draw_backend_literal:n { restore } + } +%% File: l3backend-graphics.dtx +\cs_new_protected:Npn \__graphics_backend_loaded:n #1 + { + \cs_if_exist:NTF \hook_gput_code:nnn + { + \hook_gput_code:nnn + { package / l3graphics / after } + { backend } + {#1} + } + {#1} + } +\__graphics_backend_loaded:n + { \seq_set_from_clist:Nn \l_graphics_search_ext_seq { .eps , .ps } } +\__graphics_backend_loaded:n + { + \cs_new_eq:NN \__graphics_backend_getbb_eps:n \__graphics_read_bb:n + \cs_new_eq:NN \__graphics_backend_getbb_ps:n \__graphics_read_bb:n + } +\cs_new_protected:Npn \__graphics_backend_include_eps:n #1 + { + \__kernel_backend_literal:e + { + PSfile = #1 \c_space_tl + llx = \dim_to_decimal_in_bp:n \l__graphics_llx_dim \c_space_tl + lly = \dim_to_decimal_in_bp:n \l__graphics_lly_dim \c_space_tl + urx = \dim_to_decimal_in_bp:n \l__graphics_urx_dim \c_space_tl + ury = \dim_to_decimal_in_bp:n \l__graphics_ury_dim + } + } +\cs_new_eq:NN \__graphics_backend_include_ps:n \__graphics_backend_include_eps:n +\__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 } +\cs_new_protected:Npn \__pdf_backend_catalog_gput:nn #1#2 + { \__pdf_backend_pdfmark:n { { Catalog } << /#1 ~ #2 >> /PUT } } +\cs_new_protected:Npn \__pdf_backend_info_gput:nn #1#2 + { \__pdf_backend_pdfmark:n { /#1 ~ #2 /DOCINFO } } +\cs_new_protected:Npn \__pdf_backend_object_new: + { \int_gincr:N \g__pdf_backend_object_int } +\cs_new:Npn \__pdf_backend_object_ref:n #1 { { pdf.obj #1 } } +\cs_new_eq:NN \__pdf_backend_object_id:n \__pdf_backend_object_ref:n +\cs_new_protected:Npn \__pdf_backend_object_write:nnn #1#2#3 + { + \__pdf_backend_object_write_aux:nnn + { \__pdf_backend_object_ref:n {#1} } + {#2} {#3} + } +\cs_generate_variant:Nn \__pdf_backend_object_write:nnn { nne } +\cs_new_protected:Npn \__pdf_backend_object_write_aux:nnn #1#2#3 + { + \__pdf_backend_pdfmark:e + { + /_objdef ~ #1 + /type + \str_case:nn {#2} + { + { array } { /array } + { dict } { /dict } + { fstream } { /stream } + { stream } { /stream } + } + /OBJ + } + \use:c { __pdf_backend_object_write_ #2 :nn } {#1} {#3} + } +\cs_new_protected:Npn \__pdf_backend_object_write_array:nn #1#2 + { + \__pdf_backend_pdfmark:e + { #1 ~0~ [ ~ \exp_not:n {#2} ~ ] ~ /PUTINTERVAL } + } +\cs_new_protected:Npn \__pdf_backend_object_write_dict:nn #1#2 + { + \__pdf_backend_pdfmark:e + { #1 << \exp_not:n {#2} >> /PUT } + } +\cs_new_protected:Npn \__pdf_backend_object_write_fstream:nn #1#2 + { + \exp_args:Ne + \__pdf_backend_object_write_fstream:nnn {#1} #2 + } +\cs_new_protected:Npn \__pdf_backend_object_write_fstream:nnn #1#2#3 + { + \__kernel_backend_postscript:n + { + SDict ~ begin ~ + mark ~ #1 ~ << #2 >> /PUT ~ pdfmark ~ + mark ~ #1 ~ ( #3 )~ ( r )~ file ~ /PUT ~ pdfmark ~ + end + } + } +\cs_new_protected:Npn \__pdf_backend_object_write_stream:nn #1#2 + { + \exp_args:Ne + \__pdf_backend_object_write_stream:nnn {#1} #2 + } +\cs_new_protected:Npn \__pdf_backend_object_write_stream:nnn #1#2#3 + { + \__kernel_backend_postscript:n + { + mark ~ #1 ~ ( #3 ) /PUT ~ pdfmark ~ + mark ~ #1 ~ << #2 >> /PUT ~ pdfmark + } + } +\cs_new_protected:Npn \__pdf_backend_object_now:nn #1#2 + { + \int_gincr:N \g__pdf_backend_object_int + \__pdf_backend_object_write_aux:nnn + { { pdf.obj \int_use:N \g__pdf_backend_object_int } } + {#1} {#2} + } +\cs_generate_variant:Nn \__pdf_backend_object_now:nn { ne } +\cs_new:Npn \__pdf_backend_object_last: + { { 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@hook + { + \tl_put_right:Nn \@makecol@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 } + \__pdf_backend_pdfmark:e + { + /View + [ + \str_case:nnF {#2} + { + { xyz } { /XYZ ~ pdf.dest.point ~ null } + { fit } { /Fit } + { fitb } { /FitB } + { fitbh } { /FitBH ~ pdf.dest.y } + { fitbv } { /FitBV ~ pdf.dest.x } + { fith } { /FitH ~ pdf.dest.y } + { fitv } { /FitV ~ pdf.dest.x } + { fitr } { /Fit } + } + { + /XYZ ~ pdf.dest.point ~ \fp_eval:n { (#2) / 100 } + } + ] + /Dest ( \exp_not:n {#1} ) cvn + /DEST + } + } +\cs_new_protected:Npn \__pdf_backend_destination:nnnn #1#2#3#4 + { + \exp_args:Ne \__pdf_backend_destination_aux:nnnn + { \dim_eval:n {#2} } {#1} {#3} {#4} + } +\cs_new_protected:Npn \__pdf_backend_destination_aux:nnnn #1#2#3#4 + { + \vbox_to_zero:n + { + \__kernel_kern:n {#4} + \hbox:n { \__kernel_backend_postscript:n { pdf.save.ll } } + \tex_vss:D + } + \__kernel_kern:n {#1} + \vbox_to_zero:n + { + \__kernel_kern:n { -#3 } + \hbox:n { \__kernel_backend_postscript:n { pdf.save.ur } } + \tex_vss:D + } + \__kernel_kern:n { -#1 } + \__pdf_backend_pdfmark:n + { + /View + [ + /FitR ~ + pdf.llx ~ pdf.lly ~ pdf.dest2device ~ + pdf.urx ~ pdf.ury ~ pdf.dest2device + ] + /Dest ( #2 ) cvn + /DEST + } + } +\cs_new_protected:Npn \__pdf_backend_compresslevel:n #1 + { + \int_compare:nNnT {#1} = 0 + { + \__kernel_backend_literal_postscript:n + { + /setdistillerparams ~ where + { pop << /CompressPages ~ false >> setdistillerparams } + if + } + } + } +\cs_new_protected:Npn \__pdf_backend_compress_objects:n #1 + { + \bool_if:nF {#1} + { + \__kernel_backend_literal_postscript:n + { + /setdistillerparams ~ where + { pop << /CompressStreams ~ false >> setdistillerparams } + if + } + } + } +\cs_new_protected:Npn \__pdf_backend_version_major_gset:n #1 + { + \cs_gset:Npe \__pdf_backend_version_major: { \int_eval:n {#1} } + } +\cs_new_protected:Npn \__pdf_backend_version_minor_gset:n #1 + { + \cs_gset:Npe \__pdf_backend_version_minor: { \int_eval:n {#1} } + } +\cs_new:Npn \__pdf_backend_version_major: { -1 } +\cs_new:Npn \__pdf_backend_version_minor: { -1 } +\cs_new_protected:Npn \__pdf_backend_bdc:nn #1#2 + { \__pdf_backend_pdfmark:n { /#1 ~ #2 /BDC } } +\cs_new_protected:Npn \__pdf_backend_emc: + { \__pdf_backend_pdfmark:n { /EMC } } +\cs_new_protected:Npn \__pdf_backend_pagesize_gset:nn #1#2 + { + \__kernel_backend_first_shipout:n + { + \__kernel_backend_literal:e + { + papersize = \dim_eval:n {#1} , \dim_eval:n {#2} + } + } + } +%% File: l3backend-opacity.dtx +\cs_new_protected:Npn \__opacity_backend_select:n #1 + { + \__opacity_backend:nnn {#1} { fill } { ca } + \__opacity_backend:nnn {#1} { stroke } { CA } + } +\cs_new_protected:Npn \__opacity_backend_fill:n #1 + { + \__opacity_backend:nnn + { #1 } + { fill } + { ca } + } +\cs_new_protected:Npn \__opacity_backend_stroke:n #1 + { + \__opacity_backend:nnn + { #1 } + { stroke } + { CA } + } +\cs_new_protected:Npn \__opacity_backend:nnn #1#2#3 + { + \__kernel_backend_postscript:n + { + product ~ (Ghostscript) ~ search + { + pop ~ pop ~ pop ~ + #1 ~ .set #2 constantalpha + } + { + pop ~ + mark ~ + /#3 ~ #1 + /SetTransparency ~ + pdfmark + } + ifelse + } + } +%% +%% +%% End of file `l3backend-dvips.def'. diff --git a/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.pro b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.pro new file mode 100644 index 00000000000..574b83c8b1a --- /dev/null +++ b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvips.pro @@ -0,0 +1,405 @@ +%% +%% This is file `l3backend-dvips.pro', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3backend-header.dtx (with options: `header,dvips') +%% +%% Copyright (C) 2019-2024 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. +%% +%% File: l3backend-header.dtx +/color.sc { } def +TeXDict begin +/TeXcolorseparation { setcolor } def +end +true setglobal +/pdf.globaldict 4 dict def +false setglobal +/pdf.cvs { 65534 string cvs } def +/pdf.dvi.pt { 72.27 mul Resolution div } def +/pdf.pt.dvi { 72.27 div Resolution mul } def +/pdf.rect.ht { dup 1 get neg exch 3 get add } def +/pdf.linkmargin { 1 pdf.pt.dvi } def +/pdf.linkdp.pad { 0 } def +/pdf.linkht.pad { 0 } def +/pdf.rect + { /Rect [ pdf.llx pdf.lly pdf.urx pdf.ury ] } def +/pdf.save.ll + { + currentpoint + /pdf.lly exch def + /pdf.llx exch def + } + def +/pdf.save.ur + { + currentpoint + /pdf.ury exch def + /pdf.urx exch def + } + def +/pdf.save.linkll + { + currentpoint + pdf.linkmargin add + pdf.linkdp.pad add + /pdf.lly exch def + pdf.linkmargin sub + /pdf.llx exch def + } + def +/pdf.save.linkur + { + currentpoint + pdf.linkmargin sub + pdf.linkht.pad sub + /pdf.ury exch def + pdf.linkmargin add + /pdf.urx exch def + } + def +/pdf.dest.anchor + { + currentpoint exch + pdf.dvi.pt 72 add + /pdf.dest.x exch def + pdf.dvi.pt + vsize 72 sub exch sub + /pdf.dest.y exch def + } + def +/pdf.dest.point + { pdf.dest.x pdf.dest.y } def +/pdf.dest2device + { + /pdf.dest.y exch def + /pdf.dest.x exch def + matrix currentmatrix + matrix defaultmatrix + matrix invertmatrix + matrix concatmatrix + cvx exec + /pdf.dev.y exch def + /pdf.dev.x exch def + /pdf.tmpd exch def + /pdf.tmpc exch def + /pdf.tmpb exch def + /pdf.tmpa exch def + pdf.dest.x pdf.tmpa mul + pdf.dest.y pdf.tmpc mul add + pdf.dev.x add + pdf.dest.x pdf.tmpb mul + pdf.dest.y pdf.tmpd mul add + pdf.dev.y add + } + def +/pdf.bordertracking false def +/pdf.bordertracking.begin + { + SDict /pdf.bordertracking true put + SDict /pdf.leftboundary undef + SDict /pdf.rightboundary undef + /a where + { + /a + { + currentpoint pop + SDict /pdf.rightboundary known dup + { + SDict /pdf.rightboundary get 2 index lt + { not } + if + } + if + { pop } + { SDict exch /pdf.rightboundary exch put } + ifelse + moveto + currentpoint pop + SDict /pdf.leftboundary known dup + { + SDict /pdf.leftboundary get 2 index gt + { not } + if + } + if + { pop } + { SDict exch /pdf.leftboundary exch put } + ifelse + } + put + } + if + } + def +/pdf.bordertracking.end + { + /a where { /a { moveto } put } if + /x where { /x { 0 exch rmoveto } put } if + SDict /pdf.leftboundary known + { pdf.outerbox 0 pdf.leftboundary put } + if + SDict /pdf.rightboundary known + { pdf.outerbox 2 pdf.rightboundary put } + if + SDict /pdf.bordertracking false put + } + def + /pdf.bordertracking.endpage +{ + pdf.bordertracking + { + pdf.bordertracking.end + true setglobal + pdf.globaldict + /pdf.brokenlink.rect [ pdf.outerbox aload pop ] put + pdf.globaldict + /pdf.brokenlink.skip pdf.baselineskip put + pdf.globaldict + /pdf.brokenlink.dict + pdf.link.dict pdf.cvs put + false setglobal + mark pdf.link.dict cvx exec /Rect + [ + pdf.llx + pdf.lly + pdf.outerbox 2 get pdf.linkmargin add + currentpoint exch pop + pdf.outerbox pdf.rect.ht sub pdf.linkmargin sub + ] + /ANN pdf.pdfmark + } + if +} + def +/pdf.bordertracking.continue + { + /pdf.link.dict pdf.globaldict + /pdf.brokenlink.dict get def + /pdf.outerbox pdf.globaldict + /pdf.brokenlink.rect get def + /pdf.baselineskip pdf.globaldict + /pdf.brokenlink.skip get def + pdf.globaldict dup dup + /pdf.brokenlink.dict undef + /pdf.brokenlink.skip undef + /pdf.brokenlink.rect undef + currentpoint + /pdf.originy exch def + /pdf.originx exch def + /a where + { + /a + { + moveto + SDict + begin + currentpoint pdf.originy ne exch + pdf.originx ne or + { + pdf.save.linkll + /pdf.lly + pdf.lly pdf.outerbox 1 get sub def + pdf.bordertracking.begin + } + if + end + } + put + } + if + /x where + { + /x + { + 0 exch rmoveto + SDict + begin + currentpoint + pdf.originy ne exch pdf.originx ne or + { + pdf.save.linkll + /pdf.lly + pdf.lly pdf.outerbox 1 get sub def + pdf.bordertracking.begin + } + if + end + } + put + } + if + } + def +/pdf.breaklink + { + pop + counttomark 2 mod 0 eq + { + counttomark /pdf.count exch def + { + pdf.count 0 eq { exit } if + counttomark 2 roll + 1 index /Rect eq + { + dup 4 array copy + dup dup + 1 get + pdf.outerbox pdf.rect.ht + pdf.linkmargin 2 mul add sub + 3 exch put + dup + pdf.outerbox 2 get + pdf.linkmargin add + 2 exch put + dup dup + 3 get + pdf.outerbox pdf.rect.ht + pdf.linkmargin 2 mul add add + 1 exch put + /pdf.currentrect exch def + pdf.breaklink.write + { + pdf.currentrect + dup + pdf.outerbox 0 get + pdf.linkmargin sub + 0 exch put + dup + pdf.outerbox 2 get + pdf.linkmargin add + 2 exch put + dup dup + 1 get + pdf.baselineskip add + 1 exch put + dup dup + 3 get + pdf.baselineskip add + 3 exch put + /pdf.currentrect exch def + pdf.breaklink.write + } + 1 index 3 get + pdf.linkmargin 2 mul add + pdf.outerbox pdf.rect.ht add + 2 index 1 get sub + pdf.baselineskip div round cvi 1 sub + exch + repeat + pdf.currentrect + dup + pdf.outerbox 0 get + pdf.linkmargin sub + 0 exch put + dup dup + 1 get + pdf.baselineskip add + 1 exch put + dup dup + 3 get + pdf.baselineskip add + 3 exch put + dup 2 index 2 get 2 exch put + /pdf.currentrect exch def + pdf.breaklink.write + SDict /pdf.pdfmark.good false put + exit + } + { pdf.count 2 sub /pdf.count exch def } + ifelse + } + loop + } + if + /ANN + } + def +/pdf.breaklink.write + { + counttomark 1 sub + index /_objdef eq + { + counttomark -2 roll + dup wcheck + { + readonly + counttomark 2 roll + } + { pop pop } + ifelse + } + if + counttomark 1 add copy + pop pdf.currentrect + /ANN pdfmark + } + def +/pdf.pdfmark + { + SDict /pdf.pdfmark.good true put + dup /ANN eq + { + pdf.pdfmark.store + pdf.pdfmark.dict + begin + Subtype /Link eq + currentdict /Rect known and + SDict /pdf.outerbox known and + SDict /pdf.baselineskip known and + { + Rect 3 get + pdf.linkmargin 2 mul add + pdf.outerbox pdf.rect.ht add + Rect 1 get sub + pdf.baselineskip div round cvi 0 gt + { pdf.breaklink } + if + } + if + end + SDict /pdf.outerbox undef + SDict /pdf.baselineskip undef + currentdict /pdf.pdfmark.dict undef + } + if + pdf.pdfmark.good + { pdfmark } + { cleartomark } + ifelse + } + def +/pdf.pdfmark.store + { + /pdf.pdfmark.dict 65534 dict def + counttomark 1 add copy + pop + { + dup mark eq + { + pop + exit + } + { + pdf.pdfmark.dict + begin def end + } + ifelse + } + loop +} + def +%% +%% +%% End of file `l3backend-dvips.pro'. diff --git a/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvisvgm.def b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvisvgm.def new file mode 100644 index 00000000000..e1483003cc7 --- /dev/null +++ b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-dvisvgm.def @@ -0,0 +1,672 @@ +%% +%% This is file `l3backend-dvisvgm.def', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3backend-basics.dtx (with options: `package,dvisvgm') +%% l3backend-color.dtx (with options: `package,dvisvgm') +%% l3backend-box.dtx (with options: `package,dvisvgm') +%% l3backend-draw.dtx (with options: `package,dvisvgm') +%% l3backend-graphics.dtx (with options: `package,dvisvgm') +%% l3backend-pdf.dtx (with options: `package,dvisvgm') +%% l3backend-opacity.dtx (with options: `package,dvisvgm') +%% +%% Copyright (C) 2019-2024 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. +%% +%% File: l3backend-basics.dtx +\ProvidesExplFile + {l3backend-dvisvgm.def}{2024-04-11}{} + {L3 backend support: dvisvgm} +\cs_if_exist:NTF \__kernel_dependency_version_check:nn + { + \__kernel_dependency_version_check:nn {2023-10-10} + {l3backend-dvisvgm.def} + } + { + \cs_if_exist_use:cF { @latex@error } { \errmessage } + { + Mismatched~LaTeX~support~files~detected. \MessageBreak + Loading~aborted! + } + { \use:c { @ehd } } + \tex_endinput:D + } +\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} } } +\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 } +\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 } +\int_new:N \g__kernel_backend_scope_int +\int_new:N \l__kernel_backend_scope_int +\cs_new_protected:Npn \__kernel_backend_scope_begin: + { + \__kernel_backend_literal_svg:n { } + \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 { } } + \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 { } + \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 { } + \int_gincr:N \g__kernel_backend_scope_int + } +\cs_generate_variant:Nn \__kernel_backend_scope:n { e } +%% File: l3backend-color.dtx +\cs_new_protected:Npn \__color_backend_select_cmyk:n #1 + { \__color_backend_select:n { cmyk ~ #1 } } +\cs_new_protected:Npn \__color_backend_select_gray:n #1 + { \__color_backend_select:n { gray ~ #1 } } +\cs_new_protected:Npn \__color_backend_select_named:n #1 + { \__color_backend_select:n { ~ #1 } } +\cs_new_protected:Npn \__color_backend_select_rgb:n #1 + { \__color_backend_select:n { rgb ~ #1 } } +\cs_new_protected:Npn \__color_backend_select:n #1 + { + \__kernel_backend_literal:n { color~push~ #1 } + } +\cs_new_protected:Npn \__color_backend_reset: + { \__kernel_backend_literal:n { color~pop } } +\cs_new_protected:Npn \__color_backend_select_separation:nn #1#2 { } +\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn +\cs_new_protected:Npn \__color_backend_separation_init:nnnnn #1#2#3#4#5 { } +\cs_new_protected:Npn \__color_backend_separation_init_CIELAB:nnnnnn #1#2#3 { } +\cs_new_protected:Npn \__color_backend_select_iccbased:nn #1#2 + { + \__kernel_backend_literal_svg:e + { + + } + } +\cs_new_protected:Npn \__color_backend_fill_cmyk:n #1 + { \__color_backend_fill:n { cmyk ~ #1 } } +\cs_new_protected:Npn \__color_backend_fill_gray:n #1 + { \__color_backend_fill:n { gray ~ #1 } } +\cs_new_protected:Npn \__color_backend_fill_rgb:n #1 + { \__color_backend_fill:n { rgb ~ #1 } } +\cs_new_protected:Npn \__color_backend_fill:n #1 + { + \__kernel_backend_literal:n { color~push~ #1 } + } +\cs_new_protected:Npn \__color_backend_stroke_cmyk:n #1 + { \__color_backend_cmyk:w #1 \s__color_stop } +\cs_new_protected:Npn \__color_backend_stroke_cmyk:w + #1 ~ #2 ~ #3 ~ #4 \s__color_stop + { + \use:e + { + \__color_backend:nnn + { \fp_eval:n { -100 * ( 1 - min ( 1 , #1 + #4 ) ) } } + { \fp_eval:n { -100 * ( 1 - min ( 1 , #2 + #4 ) ) } } + { \fp_eval:n { -100 * ( 1 - min ( 1 , #3 + #4 ) ) } } + } + } +\cs_new_protected:Npn \__color_backend_stroke_gray:n #1 + { + \use:e + { + \__color_backend_stroke_gray_aux:n + { \fp_eval:n { 100 * (#1) } } + } + } +\cs_new_protected:Npn \__color_backend_stroke_gray_aux:n #1 + { \__color_backend:nnn {#1} {#1} {#1} } +\cs_new_protected:Npn \__color_backend_stroke_rgb:n #1 + { \__color_backend_rgb:w #1 \s__color_stop } +\cs_new_protected:Npn \__color_backend_stroke_rgb:w + #1 ~ #2 ~ #3 \s__color_stop + { + \use:e + { + \__color_backend:nnn + { \fp_eval:n { 100 * (#1) } } + { \fp_eval:n { 100 * (#2) } } + { \fp_eval:n { 100 * (#3) } } + } + } +\cs_new_protected:Npe \__color_backend:nnn #1#2#3 + { + \__kernel_backend_scope:n + { + stroke = + " + rgb + ( + #1 \c_percent_str , + #2 \c_percent_str , + #3 \c_percent_str + ) + " + } + } +\cs_new_protected:Npn \__color_backend_fill_separation:nn #1#2 { } +\cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2 { } +\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn +\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn +\cs_new_eq:NN \__color_backend_fill_reset: \__color_backend_reset: +\cs_new_protected:Npn \__color_backend_stroke_reset: { } +\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3 { } +\cs_new_protected:Npn \__color_backend_iccbased_init:nnn #1#2#3 { } +%% File: l3backend-box.dtx +\cs_new_protected:Npn \__box_backend_clip:N #1 + { + \int_gincr:N \g__kernel_clip_path_int + \__kernel_backend_literal_svg:e + { < clipPath~id = " l3cp \int_use:N \g__kernel_clip_path_int " > } + \__kernel_backend_literal_svg:e + { + < + path ~ d = + " + M ~ 0 ~ + \dim_to_decimal:n { -\box_dp:N #1 } ~ + L ~ \dim_to_decimal:n { \box_wd:N #1 } ~ + \dim_to_decimal:n { -\box_dp:N #1 } ~ + L ~ \dim_to_decimal:n { \box_wd:N #1 } ~ + \dim_to_decimal:n { \box_ht:N #1 + \box_dp:N #1 } ~ + L ~ 0 ~ + \dim_to_decimal:n { \box_ht:N #1 + \box_dp:N #1 } ~ + Z + " + /> + } + \__kernel_backend_literal_svg:n + { < /clipPath > } + \__kernel_backend_scope_begin:n + { + transform = + " + translate ( { ?x } , { ?y } ) ~ + scale ( 1 , -1 ) + " + } + \__kernel_backend_scope:e + { + clip-path = + "url ( \c_hash_str l3cp \int_use:N \g__kernel_clip_path_int ) " + } + \__kernel_backend_scope:n + { + transform = + " + scale ( -1 , 1 ) ~ + translate ( { ?x } , { ?y } ) ~ + scale ( -1 , -1 ) + " + } + \box_use:N #1 + \__kernel_backend_scope_end: + } +\int_new:N \g__kernel_clip_path_int +\cs_new_protected:Npn \__box_backend_rotate:Nn #1#2 + { + \__kernel_backend_scope_begin:e + { + transform = + " + rotate + ( \fp_eval:n { round ( -(#2) , 5 ) } , ~ { ?x } , ~ { ?y } ) + " + } + \box_use:N #1 + \__kernel_backend_scope_end: + } +\cs_new_protected:Npn \__box_backend_scale:Nnn #1#2#3 + { + \__kernel_backend_scope_begin:e + { + transform = + " + translate ( { ?x } , { ?y } ) ~ + scale + ( + \fp_eval:n { round ( -#2 , 5 ) } , + \fp_eval:n { round ( -#3 , 5 ) } + ) ~ + translate ( { ?x } , { ?y } ) ~ + scale ( -1 ) + " + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +%% File: l3backend-draw.dtx +\cs_new_eq:NN \__draw_backend_literal:n \__kernel_backend_literal_svg:n +\cs_generate_variant:Nn \__draw_backend_literal:n { e } +\cs_new_eq:NN \__draw_backend_scope_begin: \__kernel_backend_scope_begin: +\cs_new_eq:NN \__draw_backend_scope_end: \__kernel_backend_scope_end: +\cs_new_protected:Npn \__draw_backend_begin: + { + \__kernel_backend_scope_begin: + \__kernel_backend_scope:n { transform="translate({?x},{?y})~scale(1,-1)" } + } +\cs_new_eq:NN \__draw_backend_end: \__kernel_backend_scope_end: +\cs_new_protected:Npn \__draw_backend_moveto:nn #1#2 + { + \__draw_backend_add_to_path:n + { M ~ \dim_to_decimal:n {#1} ~ \dim_to_decimal:n {#2} } + } +\cs_new_protected:Npn \__draw_backend_lineto:nn #1#2 + { + \__draw_backend_add_to_path:n + { L ~ \dim_to_decimal:n {#1} ~ \dim_to_decimal:n {#2} } + } +\cs_new_protected:Npn \__draw_backend_rectangle:nnnn #1#2#3#4 + { + \__draw_backend_add_to_path:n + { + M ~ \dim_to_decimal:n {#1} ~ \dim_to_decimal:n {#2} + h ~ \dim_to_decimal:n {#3} ~ + v ~ \dim_to_decimal:n {#4} ~ + h ~ \dim_to_decimal:n { -#3 } ~ + Z + } + } +\cs_new_protected:Npn \__draw_backend_curveto:nnnnnn #1#2#3#4#5#6 + { + \__draw_backend_add_to_path:n + { + C ~ + \dim_to_decimal:n {#1} ~ \dim_to_decimal:n {#2} ~ + \dim_to_decimal:n {#3} ~ \dim_to_decimal:n {#4} ~ + \dim_to_decimal:n {#5} ~ \dim_to_decimal:n {#6} + } + } +\cs_new_protected:Npn \__draw_backend_add_to_path:n #1 + { + \tl_gset:Ne \g__draw_backend_path_tl + { + \g__draw_backend_path_tl + \tl_if_empty:NF \g__draw_backend_path_tl { \c_space_tl } + #1 + } + } +\tl_new:N \g__draw_backend_path_tl +\cs_new_protected:Npn \__draw_backend_evenodd_rule: + { \__kernel_backend_scope:n { fill-rule="evenodd" } } +\cs_new_protected:Npn \__draw_backend_nonzero_rule: + { \__kernel_backend_scope:n { fill-rule="nonzero" } } +\cs_new_protected:Npn \__draw_backend_closepath: + { \__draw_backend_add_to_path:n { Z } } +\cs_new_protected:Npn \__draw_backend_path:n #1 + { + \bool_if:NTF \g__draw_draw_clip_bool + { + \int_gincr:N \g__kernel_clip_path_int + \__draw_backend_literal:e + { + < clipPath~id = " l3cp \int_use:N \g__kernel_clip_path_int " > + { ?nl } + { ?nl } + < /clipPath > { ? nl } + < + use~xlink:href = + "\c_hash_str l3path \int_use:N \g__draw_backend_path_int " ~ + #1 + /> + } + \__kernel_backend_scope:e + { + clip-path = + "url( \c_hash_str l3cp \int_use:N \g__kernel_clip_path_int)" + } + } + { + \__draw_backend_literal:e + { } + } + \tl_gclear:N \g__draw_backend_path_tl + \bool_gset_false:N \g__draw_draw_clip_bool + } +\int_new:N \g__draw_backend_path_int +\cs_new_protected:Npn \__draw_backend_stroke: + { \__draw_backend_path:n { style="fill:none" } } +\cs_new_protected:Npn \__draw_backend_closestroke: + { + \__draw_backend_closepath: + \__draw_backend_stroke: + } +\cs_new_protected:Npn \__draw_backend_fill: + { \__draw_backend_path:n { style="stroke:none" } } +\cs_new_protected:Npn \__draw_backend_fillstroke: + { \__draw_backend_path:n { } } +\cs_new_protected:Npn \__draw_backend_clip: + { \bool_gset_true:N \g__draw_draw_clip_bool } +\bool_new:N \g__draw_draw_clip_bool +\cs_new_protected:Npn \__draw_backend_discardpath: + { + \bool_if:NT \g__draw_draw_clip_bool + { + \int_gincr:N \g__kernel_clip_path_int + \__draw_backend_literal:e + { + < clipPath~id = " l3cp \int_use:N \g__kernel_clip_path_int " > + { ?nl } + { ?nl } + < /clipPath > + } + \__kernel_backend_scope:e + { + clip-path = + "url( \c_hash_str l3cp \int_use:N \g__kernel_clip_path_int)" + } + } + \tl_gclear:N \g__draw_backend_path_tl + \bool_gset_false:N \g__draw_draw_clip_bool + } +\cs_new_protected:Npn \__draw_backend_dash_pattern:nn #1#2 + { + \use:e + { + \__draw_backend_dash_aux:nn + { \clist_map_function:nN {#1} \__draw_backend_dash:n } + { \dim_to_decimal:n {#2} } + } + } +\cs_new:Npn \__draw_backend_dash:n #1 + { , \dim_to_decimal_in_bp:n {#1} } +\cs_new_protected:Npn \__draw_backend_dash_aux:nn #1#2 + { + \__kernel_backend_scope:e + { + stroke-dasharray = + " + \tl_if_empty:nTF {#1} + { none } + { \use_none:n #1 } + " ~ + stroke-offset=" #2 " + } + } +\cs_new_protected:Npn \__draw_backend_linewidth:n #1 + { \__kernel_backend_scope:e { stroke-width=" \dim_to_decimal:n {#1} " } } +\cs_new_protected:Npn \__draw_backend_miterlimit:n #1 + { \__kernel_backend_scope:e { stroke-miterlimit=" #1 " } } +\cs_new_protected:Npn \__draw_backend_cap_butt: + { \__kernel_backend_scope:n { stroke-linecap="butt" } } +\cs_new_protected:Npn \__draw_backend_cap_round: + { \__kernel_backend_scope:n { stroke-linecap="round" } } +\cs_new_protected:Npn \__draw_backend_cap_rectangle: + { \__kernel_backend_scope:n { stroke-linecap="square" } } +\cs_new_protected:Npn \__draw_backend_join_miter: + { \__kernel_backend_scope:n { stroke-linejoin="miter" } } +\cs_new_protected:Npn \__draw_backend_join_round: + { \__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 + { + \__kernel_backend_scope:n + { + transform = + " matrix ( #1 , #2 , #3 , #4 , 0pt , 0pt ) " + } + } +\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_literal_svg:n + { + < g~ + stroke="none"~ + transform="scale(-1,1)~translate({?x},{?y})~scale(-1,-1)" + > + } + \box_set_wd:Nn #1 { 0pt } + \box_set_ht:Nn #1 { 0pt } + \box_set_dp:Nn #1 { 0pt } + \box_use:N #1 + \__kernel_backend_literal_svg:n { } + \__kernel_backend_scope_end: + } +%% File: l3backend-graphics.dtx +\cs_new_protected:Npn \__graphics_backend_loaded:n #1 + { + \cs_if_exist:NTF \hook_gput_code:nnn + { + \hook_gput_code:nnn + { package / l3graphics / after } + { backend } + {#1} + } + {#1} + } +\__graphics_backend_loaded:n + { + \seq_set_from_clist:Nn + \l_graphics_search_ext_seq + { .svg , .pdf , .eps , .ps , .png , .jpg , .jpeg } + } +\cs_new_protected:Npn \__graphics_backend_getbb_svg:n #1 + { + \__graphics_bb_restore:nF {#1} + { + \ior_open:Nn \l__graphics_internal_ior {#1} + \ior_if_eof:NTF \l__graphics_internal_ior + { \msg_error:nnn { graphics } { graphic-not-found } {#1} } + { + \dim_zero:N \l__graphics_llx_dim + \dim_zero:N \l__graphics_lly_dim + \dim_set:Nn \l__graphics_urx_dim { -\c_max_dim } + \dim_set:Nn \l__graphics_ury_dim { -\c_max_dim } + \ior_str_map_inline:Nn \l__graphics_internal_ior + { + \dim_compare:nNnT \l__graphics_urx_dim = { -\c_max_dim } + { + \__graphics_backend_getbb_svg_auxi:nNn + { width } \l__graphics_urx_dim {##1} + } + \dim_compare:nNnT \l__graphics_ury_dim = { -\c_max_dim } + { + \__graphics_backend_getbb_svg_auxi:nNn + { height } \l__graphics_ury_dim {##1} + } + \bool_lazy_and:nnF + { \dim_compare_p:nNn \l__graphics_urx_dim = { -\c_max_dim } } + { \dim_compare_p:nNn \l__graphics_ury_dim = { -\c_max_dim } } + { \ior_map_break: } + } + \__graphics_bb_save:n {#1} + } + \ior_close:N \l__graphics_internal_ior + } + } +\cs_new_protected:Npn \__graphics_backend_getbb_svg_auxi:nNn #1#2#3 + { + \use:e + { + \cs_set_protected:Npn \__graphics_backend_getbb_svg_auxii:w + ##1 \tl_to_str:n {#1} = ##2 \tl_to_str:n {#1} = ##3 + \s__graphics_stop + } + { + \tl_if_blank:nF {##2} + { + \peek_remove_spaces:n + { + \peek_meaning:NTF ' % ' + { \__graphics_backend_getbb_svg_auxiii:Nw #2 } + { + \peek_meaning:NTF " % " + { \__graphics_backend_getbb_svg_auxiv:Nw #2 } + { \__graphics_backend_getbb_svg_auxv:Nw #2 } + } + } + ##2 \s__graphics_stop + } + } + \use:e + { + \__graphics_backend_getbb_svg_auxii:w #3 + \tl_to_str:n {#1} = \tl_to_str:n {#1} = + \s__graphics_stop + } + } +\cs_new_protected:Npn \__graphics_backend_getbb_svg_auxii:w { } +\cs_new_protected:Npn \__graphics_backend_getbb_svg_auxiii:Nw #1 ' #2 ' #3 \s__graphics_stop + { \__graphics_backend_getbb_svg_auxvi:Nn #1 {#2} } +\cs_new_protected:Npn \__graphics_backend_getbb_svg_auxiv:Nw #1 " #2 " #3 \s__graphics_stop + { \__graphics_backend_getbb_svg_auxvi:Nn #1 {#2} } +\cs_new_protected:Npn \__graphics_backend_getbb_svg_auxv:Nw #1 #2 ~ #3 \s__graphics_stop + { \__graphics_backend_getbb_svg_auxvi:Nn #1 {#2} } +\cs_new_protected:Npn \__graphics_backend_getbb_svg_auxvi:Nn #1#2 + { + \tex_afterassignment:D \__graphics_backend_getbb_svg_auxvii:w + \l__graphics_internal_dim #2 bp \scan_stop: + \dim_set_eq:NN #1 \l__graphics_internal_dim + } +\cs_new_protected:Npn \__graphics_backend_getbb_svg_auxvii:w #1 \scan_stop: { } +\__graphics_backend_loaded:n + { + \cs_new_eq:NN \__graphics_backend_getbb_eps:n \__graphics_read_bb:n + \cs_new_eq:NN \__graphics_backend_getbb_ps:n \__graphics_read_bb:n + } +\cs_new_protected:Npn \__graphics_backend_getbb_jpg:n #1 + { + \int_zero:N \l__graphics_page_int + \tl_clear:N \l__graphics_pagebox_tl + \__graphics_extract_bb:n {#1} + } +\cs_new_eq:NN \__graphics_backend_getbb_jpeg:n \__graphics_backend_getbb_jpg:n +\cs_new_eq:NN \__graphics_backend_getbb_png:n \__graphics_backend_getbb_jpg:n +\cs_new_protected:Npn \__graphics_backend_getbb_pdf:n #1 + { + \tl_clear:N \l__graphics_decodearray_str + \bool_set_false:N \l__graphics_interpolate_bool + \__graphics_extract_bb:n {#1} + } +\cs_new_protected:Npn \__graphics_backend_include_eps:n #1 + { \__graphics_backend_include:nn { PSfile } {#1} } +\cs_new_eq:NN \__graphics_backend_include_ps:n \__graphics_backend_include_eps:n +\cs_new_protected:Npn \__graphics_backend_include_pdf:n #1 + { \__graphics_backend_include:nn { pdffile } {#1} } +\cs_new_protected:Npn \__graphics_backend_include:nn #1#2 + { + \__kernel_backend_literal:e + { + #1 = #2 \c_space_tl + llx = \dim_to_decimal_in_bp:n \l__graphics_llx_dim \c_space_tl + lly = \dim_to_decimal_in_bp:n \l__graphics_lly_dim \c_space_tl + urx = \dim_to_decimal_in_bp:n \l__graphics_urx_dim \c_space_tl + ury = \dim_to_decimal_in_bp:n \l__graphics_ury_dim + } + } +\cs_new_protected:Npn \__graphics_backend_include_svg:n #1 + { + \box_move_up:nn { \l__graphics_ury_dim } + { + \hbox:n + { + \__kernel_backend_literal:e + { + dvisvgm:img~ + \dim_to_decimal:n { \l__graphics_urx_dim } ~ + \dim_to_decimal:n { \l__graphics_ury_dim } ~ + \__graphics_backend_include_dequote:w #1 " #1 " \s__graphics_stop + } + } + } + } +\cs_new_eq:NN \__graphics_backend_include_png:n \__graphics_backend_include_svg:n +\cs_new_eq:NN \__graphics_backend_include_jpeg:n \__graphics_backend_include_svg:n +\cs_new_eq:NN \__graphics_backend_include_jpg:n \__graphics_backend_include_svg:n +\cs_new:Npn \__graphics_backend_include_dequote:w #1 " #2 " #3 \s__graphics_stop + {#2} +\__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 { } +\cs_new_protected:Npn \__pdf_backend_info_gput:nn #1#2 { } +\cs_new_protected:Npn \__pdf_backend_object_new: { } +\cs_new:Npn \__pdf_backend_object_ref:n #1 { } +\cs_new:Npn \__pdf_backend_object_id:n #1 { } +\cs_new_protected:Npn \__pdf_backend_object_write:nnn #1#2#3 { } +\cs_new_protected:Npn \__pdf_backend_object_write:nne #1#2#3 { } +\cs_new_protected:Npn \__pdf_backend_object_now:nn #1#2 { } +\cs_new_protected:Npn \__pdf_backend_object_now:ne #1#2 { } +\cs_new:Npn \__pdf_backend_object_last: { } +\cs_new:Npn \__pdf_backend_pageobject_ref:n #1 { } +\cs_new_protected:Npn \__pdf_backend_compresslevel:n #1 { } +\cs_new_protected:Npn \__pdf_backend_compress_objects:n #1 { } +\cs_new_protected:Npn \__pdf_backend_version_major_gset:n #1 { } +\cs_new_protected:Npn \__pdf_backend_version_minor_gset:n #1 { } +\cs_new:Npn \__pdf_backend_version_major: { -1 } +\cs_new:Npn \__pdf_backend_version_minor: { -1 } +\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-opacity.dtx +\cs_new_protected:Npn \__opacity_backend_select:n #1 + { \__opacity_backend:nn {#1} { } } +\cs_new_protected:Npn \__opacity_backend_fill:n #1 + { \__opacity_backend:nn {#1} { fill- } } +\cs_new_protected:Npn \__opacity_backend_stroke:n #1 + { \__opacity_backend:nn {#1} { stroke- } } +\cs_new_protected:Npn \__opacity_backend:nn #1#2 + { \__kernel_backend_scope:e { #2 opacity = " #1 " } } +%% +%% +%% End of file `l3backend-dvisvgm.def'. diff --git a/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.def b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.def new file mode 100644 index 00000000000..cdd871cceda --- /dev/null +++ b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.def @@ -0,0 +1,903 @@ +%% +%% This is file `l3backend-luatex.def', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3backend-basics.dtx (with options: `package,luatex') +%% l3backend-color.dtx (with options: `package,luatex') +%% l3backend-box.dtx (with options: `package,luatex') +%% l3backend-draw.dtx (with options: `package,luatex') +%% l3backend-graphics.dtx (with options: `package,luatex') +%% l3backend-pdf.dtx (with options: `package,luatex') +%% l3backend-opacity.dtx (with options: `package,luatex') +%% +%% Copyright (C) 2019-2024 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. +%% +%% File: l3backend-basics.dtx +\ProvidesExplFile + {l3backend-luatex.def}{2024-04-11}{} + {L3 backend support: PDF output (LuaTeX)} +\cs_if_exist:NTF \__kernel_dependency_version_check:nn + { + \__kernel_dependency_version_check:nn {2023-10-10} + {l3backend-luatex.def} + } + { + \cs_if_exist_use:cF { @latex@error } { \errmessage } + { + Mismatched~LaTeX~support~files~detected. \MessageBreak + Loading~aborted! + } + { \use:c { @ehd } } + \tex_endinput:D + } +\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} } } +\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 } +\cs_new_protected:Npn \__kernel_backend_literal_pdf:n #1 + { + \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_page:n #1 + { + \tex_pdfextension:D literal ~ + page { \exp_not:n {#1} } + } +\cs_new_protected:Npn \__kernel_backend_literal_page:e #1 + { + \tex_pdfextension:D literal ~ + page {#1} + } +\cs_new_protected:Npn \__kernel_backend_scope_begin: + { + \tex_pdfextension:D save \scan_stop: + } +\cs_new_protected:Npn \__kernel_backend_scope_end: + { + \tex_pdfextension:D restore \scan_stop: + } +\cs_new_protected:Npn \__kernel_backend_matrix:n #1 + { + \tex_pdfextension:D setmatrix + { \exp_not:n {#1} } + } +\cs_generate_variant:Nn \__kernel_backend_matrix:n { e } +%% 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 + { + \int_const:Nn #1 + { + \tex_pdffeedback:D colorstackinit ~ + \tl_if_blank:nF {#2} { #2 ~ } + {#3} + } + } +\cs_new_protected:Npn \__kernel_color_backend_stack_push:nn #1#2 + { + \tex_pdfextension:D colorstack ~ + \int_eval:n {#1} ~ push ~ {#2} + } +\cs_new_protected:Npn \__kernel_color_backend_stack_pop:n #1 + { + \tex_pdfextension:D colorstack ~ + \int_eval:n {#1} ~ pop \scan_stop: + } +\tl_new:N \l__color_backend_fill_tl +\tl_new:N \l__color_backend_stroke_tl +\tl_set:Nn \l__color_backend_fill_tl { 0 ~ g } +\tl_set:Nn \l__color_backend_stroke_tl { 0 ~ G } +\cs_new_protected:Npn \__color_backend_select_cmyk:n #1 + { \__color_backend_select:nn { #1 ~ k } { #1 ~ K } } +\cs_new_protected:Npn \__color_backend_select_gray:n #1 + { \__color_backend_select:nn { #1 ~ g } { #1 ~ G } } +\cs_new_protected:Npn \__color_backend_select_rgb:n #1 + { \__color_backend_select:nn { #1 ~ rg } { #1 ~ RG } } +\cs_new_protected:Npn \__color_backend_select:nn #1#2 + { + \tl_set:Nn \l__color_backend_fill_tl {#1} + \tl_set:Nn \l__color_backend_stroke_tl {#2} + \__kernel_color_backend_stack_push:nn \l__color_backend_stack_int { #1 ~ #2 } + } +\cs_new_protected:Npn \__color_backend_reset: + { \__kernel_color_backend_stack_pop:n \l__color_backend_stack_int } +\prop_new:N \g__color_backend_colorant_prop +\cs_new:Npe \__color_backend_devicen_colorants:n #1 + { + \exp_not:N \tl_if_blank:nF {#1} + { + \c_space_tl + << ~ + /Colorants ~ + << ~ + \exp_not:N \__color_backend_devicen_colorants:w #1 ~ + \exp_not:N \q_recursion_tail \c_space_tl + \exp_not:N \q_recursion_stop + >> ~ + >> + } + } +\cs_new:Npn \__color_backend_devicen_colorants:w #1 ~ + { + \quark_if_recursion_tail_stop:n {#1} + \prop_if_in:NnT \g__color_backend_colorant_prop {#1} + { + #1 ~ + \prop_item:Nn \g__color_backend_colorant_prop {#1} ~ + } + \__color_backend_devicen_colorants:w + } +\cs_new_protected:Npn \__color_backend_select_separation:nn #1#2 + { \__color_backend_select:nn { /#1 ~ cs ~ #2 ~ scn } { /#1 ~ CS ~ #2 ~ SCN } } +\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn +\cs_new_eq:NN \__color_backend_select_iccbased:nn \__color_backend_select_separation:nn +\cs_new_protected:Npn \__color_backend_init_resource:n #1 + { + \bool_lazy_and:nnT + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \use:e + { + \pdfmanagement_add:nnn + { Page / Resources / ColorSpace } + { #1 } + { \pdf_object_ref_last: } + } + } + } +\cs_new_protected:Npn \__color_backend_separation_init:nnnnn #1#2#3#4#5 + { + \pdf_object_unnamed_write:ne { dict } + { + /FunctionType ~ 2 + /Domain ~ [0 ~ 1] + \tl_if_blank:nF {#3} { /Range ~ [#3] } + /C0 ~ [#4] ~ + /C1 ~ [#5] /N ~ 1 + } + \exp_args:Ne \__color_backend_separation_init:nn + { \str_convert_pdfname:n {#1} } {#2} + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new_protected:Npn \__color_backend_separation_init:nn #1#2 + { + \use:e + { + \pdf_object_new:n { color \int_use:N \g__color_model_int } + \pdf_object_write:nnn { color \int_use:N \g__color_model_int } { array } + { /Separation /#1 ~ #2 ~ \pdf_object_ref_last: } + } + \prop_gput:Nne \g__color_backend_colorant_prop { /#1 } + { \pdf_object_ref_last: } + } +\cs_new_protected:Npn \__color_backend_separation_init_CIELAB:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_illuminant_CIELAB_ #1 } + { + \pdf_object_new:n { __color_illuminant_CIELAB_ #1 } + \pdf_object_write:nne { __color_illuminant_CIELAB_ #1 } { array } + { + /Lab ~ + << + /WhitePoint ~ + [ \tl_use:c { c__color_model_whitepoint_CIELAB_ #1 _tl } ] + /Range ~ [ \c__color_model_range_CIELAB_tl ] + >> + } + } + \__color_backend_separation_init:nnnnn + {#2} + { \pdf_object_ref:n { __color_illuminant_CIELAB_ #1 } } + { \c__color_model_range_CIELAB_tl } + { 100 ~ 0 ~ 0 } + {#3} + } +\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3 + { + \pdf_object_unnamed_write:ne { stream } + { + { + /FunctionType ~ 4 ~ + /Domain ~ + [ ~ + \prg_replicate:nn + { 0 \__color_backend_devicen_init:w #1 ~ \s__color_stop } + { 0 ~ 1 ~ } + ] ~ + /Range ~ + [ ~ + \str_case:nn {#2} + { + { /DeviceCMYK } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 } + { /DeviceGray } { 0 ~ 1 } + { /DeviceRGB } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 } + } ~ + ] + } + { {#3} } + } + \use:e + { + \pdf_object_new:n { color \int_use:N \g__color_model_int } + \pdf_object_write:nnn { color \int_use:N \g__color_model_int } { array } + { + /DeviceN ~ + [ ~ #1 ~ ] ~ + #2 ~ + \pdf_object_ref_last: + \__color_backend_devicen_colorants:n {#1} + } + } + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new:Npn \__color_backend_devicen_init:w #1 ~ #2 \s__color_stop + { + + 1 + \tl_if_blank:nF {#2} + { \__color_backend_devicen_init:w #2 \s__color_stop } + } +\cs_new_protected:Npn \__color_backend_iccbased_init:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_icc_ #1 } + { + \pdf_object_new:n { __color_icc_ #1 } + \pdf_object_write:nne { __color_icc_ #1 } { fstream } + { + { + /N ~ \exp_not:n { #2 } ~ + \tl_if_empty:nF { #3 } { /Range~[ #3 ] } + } + {#1} + } + } + \pdf_object_unnamed_write:ne { array } + { /ICCBased ~ \pdf_object_ref:n { __color_icc_ #1 } } + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new_protected:Npn \__color_backend_iccbased_device:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_icc_ #1 } + { + \pdf_object_new:n { __color_icc_ #1 } + \pdf_object_write:nnn { __color_icc_ #1 } { fstream } + { + { /N ~ #3 } + {#1} + } + } + \pdf_object_unnamed_write:ne { array } + { /ICCBased ~ \pdf_object_ref:n { __color_icc_ #1 } } + \__color_backend_init_resource:n { Default #2 } + } +\cs_new_protected:Npn \__color_backend_fill_cmyk:n #1 + { \__color_backend_fill:n { #1 ~ k } } +\cs_new_protected:Npn \__color_backend_fill_gray:n #1 + { \__color_backend_fill:n { #1 ~ g } } +\cs_new_protected:Npn \__color_backend_fill_rgb:n #1 + { \__color_backend_fill:n { #1 ~ rg } } +\cs_new_protected:Npn \__color_backend_fill:n #1 + { + \tl_set:Nn \l__color_backend_fill_tl {#1} + \__kernel_color_backend_stack_push:nn \l__color_backend_stack_int + { #1 ~ \l__color_backend_stroke_tl } + } +\cs_new_protected:Npn \__color_backend_stroke_cmyk:n #1 + { \__color_backend_stroke:n { #1 ~ K } } +\cs_new_protected:Npn \__color_backend_stroke_gray:n #1 + { \__color_backend_stroke:n { #1 ~ G } } +\cs_new_protected:Npn \__color_backend_stroke_rgb:n #1 + { \__color_backend_stroke:n { #1 ~ RG } } +\cs_new_protected:Npn \__color_backend_stroke:n #1 + { + \tl_set:Nn \l__color_backend_stroke_tl {#1} + \__kernel_color_backend_stack_push:nn \l__color_backend_stack_int + { \l__color_backend_fill_tl \c_space_tl #1 } + } +\cs_new_protected:Npn \__color_backend_fill_separation:nn #1#2 + { \__color_backend_fill:n { /#1 ~ cs ~ #2 ~ scn } } +\cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2 + { \__color_backend_stroke:n { /#1 ~ CS ~ #2 ~ SCN } } +\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn +\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn +\cs_new_eq:NN \__color_backend_fill_reset: \__color_backend_reset: +\cs_new_eq:NN \__color_backend_stroke_reset: \__color_backend_reset: +\lua_load_module:n {l3backend-luatex} +%% File: l3backend-box.dtx +\cs_new_protected:Npn \__box_backend_clip:N #1 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal_pdf:e + { + 0~ + \dim_to_decimal_in_bp:n { -\box_dp:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~ + re~W~n + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + \skip_horizontal:n { \box_wd:N #1 } + } +\cs_new_protected:Npn \__box_backend_rotate:Nn #1#2 + { \exp_args:NNf \__box_backend_rotate_aux:Nn #1 { \fp_eval:n {#2} } } +\cs_new_protected:Npn \__box_backend_rotate_aux:Nn #1#2 + { + \__kernel_backend_scope_begin: + \box_set_wd:Nn #1 { 0pt } + \fp_set:Nn \l__box_backend_cos_fp { round ( cosd ( #2 ) , 5 ) } + \fp_compare:nNnT \l__box_backend_cos_fp = \c_zero_fp + { \fp_zero:N \l__box_backend_cos_fp } + \fp_set:Nn \l__box_backend_sin_fp { round ( sind ( #2 ) , 5 ) } + \__kernel_backend_matrix:e + { + \fp_use:N \l__box_backend_cos_fp \c_space_tl + \fp_compare:nNnTF \l__box_backend_sin_fp = \c_zero_fp + { 0~0 } + { + \fp_use:N \l__box_backend_sin_fp + \c_space_tl + \fp_eval:n { -\l__box_backend_sin_fp } + } + \c_space_tl + \fp_use:N \l__box_backend_cos_fp + } + \box_use:N #1 + \__kernel_backend_scope_end: + } +\fp_new:N \l__box_backend_cos_fp +\fp_new:N \l__box_backend_sin_fp +\cs_new_protected:Npn \__box_backend_scale:Nnn #1#2#3 + { + \__kernel_backend_scope_begin: + \__kernel_backend_matrix:e + { + \fp_eval:n { round ( #2 , 5 ) } ~ + 0~0~ + \fp_eval:n { round ( #3 , 5 ) } + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +%% 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_protected:Npn \__draw_backend_begin: + { \__draw_backend_scope_begin: } +\cs_new_protected:Npn \__draw_backend_end: + { \__draw_backend_scope_end: } +\cs_new_eq:NN \__draw_backend_scope_begin: \__kernel_backend_scope_begin: +\cs_new_eq:NN \__draw_backend_scope_end: \__kernel_backend_scope_end: +\cs_new_protected:Npn \__draw_backend_moveto:nn #1#2 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ m } + } +\cs_new_protected:Npn \__draw_backend_lineto:nn #1#2 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ l } + } +\cs_new_protected:Npn \__draw_backend_curveto:nnnnnn #1#2#3#4#5#6 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~ + c + } + } +\cs_new_protected:Npn \__draw_backend_rectangle:nnnn #1#2#3#4 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + re + } + } +\cs_new_protected:Npn \__draw_backend_evenodd_rule: + { \bool_gset_true:N \g__draw_draw_eor_bool } +\cs_new_protected:Npn \__draw_backend_nonzero_rule: + { \bool_gset_false:N \g__draw_draw_eor_bool } +\bool_new:N \g__draw_draw_eor_bool +\cs_new_protected:Npn \__draw_backend_closepath: + { \__draw_backend_literal:n { h } } +\cs_new_protected:Npn \__draw_backend_stroke: + { \__draw_backend_literal:n { S } } +\cs_new_protected:Npn \__draw_backend_closestroke: + { \__draw_backend_literal:n { s } } +\cs_new_protected:Npn \__draw_backend_fill: + { + \__draw_backend_literal:e + { f \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_fillstroke: + { + \__draw_backend_literal:e + { B \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_clip: + { + \__draw_backend_literal:e + { W \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_discardpath: + { \__draw_backend_literal:n { n } } +\cs_new_protected:Npn \__draw_backend_dash_pattern:nn #1#2 + { + \__draw_backend_literal:e + { + [ + \exp_args:Nf \use:n + { \clist_map_function:nN {#1} \__draw_backend_dash:n } + ] ~ + \dim_to_decimal_in_bp:n {#2} ~ d + } + } +\cs_new:Npn \__draw_backend_dash:n #1 + { ~ \dim_to_decimal_in_bp:n {#1} } +\cs_new_protected:Npn \__draw_backend_linewidth:n #1 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ w } + } +\cs_new_protected:Npn \__draw_backend_miterlimit:n #1 + { \__draw_backend_literal:e { #1 ~ M } } +\cs_new_protected:Npn \__draw_backend_cap_butt: + { \__draw_backend_literal:n { 0 ~ J } } +\cs_new_protected:Npn \__draw_backend_cap_round: + { \__draw_backend_literal:n { 1 ~ J } } +\cs_new_protected:Npn \__draw_backend_cap_rectangle: + { \__draw_backend_literal:n { 2 ~ J } } +\cs_new_protected:Npn \__draw_backend_join_miter: + { \__draw_backend_literal:n { 0 ~ j } } +\cs_new_protected:Npn \__draw_backend_join_round: + { \__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 + { + \__kernel_backend_matrix:n { #1 ~ #2 ~ #3 ~ #4 } + } +\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} + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +%% File: l3backend-graphics.dtx +\cs_new_protected:Npn \__graphics_backend_loaded:n #1 + { + \cs_if_exist:NTF \hook_gput_code:nnn + { + \hook_gput_code:nnn + { package / l3graphics / after } + { backend } + {#1} + } + {#1} + } +\__graphics_backend_loaded:n + { + \seq_set_from_clist:Nn + \l_graphics_search_ext_seq + { .pdf , .eps , .ps , .png , .jpg , .jpeg } + } +\tl_new:N \l__graphics_attr_tl +\cs_new_protected:Npn \__graphics_backend_getbb_jpg:n #1 + { + \int_zero:N \l__graphics_page_int + \tl_clear:N \l__graphics_pagebox_tl + \tl_set:Ne \l__graphics_attr_tl + { + \tl_if_empty:NF \l__graphics_decodearray_str + { :D \l__graphics_decodearray_str } + \bool_if:NT \l__graphics_interpolate_bool + { :I } + \str_if_empty:NF \l__graphics_pdf_str + { :X \l__graphics_pdf_str } + } + \__graphics_backend_getbb_auxi:n {#1} + } +\cs_new_eq:NN \__graphics_backend_getbb_jpeg:n \__graphics_backend_getbb_jpg:n +\cs_new_eq:NN \__graphics_backend_getbb_png:n \__graphics_backend_getbb_jpg:n +\cs_new_protected:Npn \__graphics_backend_getbb_pdf:n #1 + { + \tl_clear:N \l__graphics_decodearray_str + \bool_set_false:N \l__graphics_interpolate_bool + \tl_set:Ne \l__graphics_attr_tl + { + : \l__graphics_pagebox_tl + \int_compare:nNnT \l__graphics_page_int > 1 + { :P \int_use:N \l__graphics_page_int } + \str_if_empty:NF \l__graphics_pdf_str + { :X \l__graphics_pdf_str } + } + \__graphics_backend_getbb_auxi:n {#1} + } +\cs_new_protected:Npn \__graphics_backend_getbb_auxi:n #1 + { + \__graphics_bb_restore:eF { #1 \l__graphics_attr_tl } + { \__graphics_backend_getbb_auxii:n {#1} } + } +\cs_new_protected:Npn \__graphics_backend_getbb_auxii:n #1 + { + \exp_args:Ne \__graphics_backend_getbb_auxiii:n + { \__graphics_backend_dequote:w #1 " #1 " \s__graphics_stop } + \int_const:cn { c__graphics_ #1 \l__graphics_attr_tl _int } + { \tex_the:D \tex_pdflastximage:D } + \__graphics_bb_save:e { #1 \l__graphics_attr_tl } + } +\cs_new_protected:Npn \__graphics_backend_getbb_auxiii:n #1 + { + \tex_immediate:D \tex_pdfximage:D + \bool_lazy_any:nT + { + { \l__graphics_interpolate_bool } + { ! \tl_if_empty_p:N \l__graphics_decodearray_str } + { ! \str_if_empty_p:N \l__graphics_pdf_str } + } + { + attr ~ + { + \tl_if_empty:NF \l__graphics_decodearray_str + { /Decode~[ \l__graphics_decodearray_str ] } + \bool_if:NT \l__graphics_interpolate_bool + { /Interpolate~true } + \l__graphics_pdf_str + } + } + \int_compare:nNnT \l__graphics_page_int > 0 + { page ~ \int_use:N \l__graphics_page_int } + \tl_if_empty:NF \l__graphics_pagebox_tl + { \l__graphics_pagebox_tl } + {#1} + \hbox_set:Nn \l__graphics_internal_box + { \tex_pdfrefximage:D \tex_pdflastximage:D } + \dim_set:Nn \l__graphics_urx_dim { \box_wd:N \l__graphics_internal_box } + \dim_set:Nn \l__graphics_ury_dim { \box_ht:N \l__graphics_internal_box } + } +\cs_new:Npn \__graphics_backend_dequote:w #1 " #2 " #3 \s__graphics_stop {#2} +\cs_new_protected:Npn \__graphics_backend_include_jpg:n #1 + { + \tex_pdfrefximage:D + \int_use:c { c__graphics_ #1 \l__graphics_attr_tl _int } + } +\cs_new_eq:NN \__graphics_backend_include_jpeg:n \__graphics_backend_include_jpg:n +\cs_new_eq:NN \__graphics_backend_include_pdf:n \__graphics_backend_include_jpg:n +\cs_new_eq:NN \__graphics_backend_include_png:n \__graphics_backend_include_jpg:n +\sys_if_shell:T + { + \str_new:N \l__graphics_backend_dir_str + \str_new:N \l__graphics_backend_name_str + \str_new:N \l__graphics_backend_ext_str + \cs_new_protected:Npn \__graphics_backend_getbb_eps:n #1 + { + \file_parse_full_name:nNNN {#1} + \l__graphics_backend_dir_str + \l__graphics_backend_name_str + \l__graphics_backend_ext_str + \exp_args:Ne \__graphics_backend_getbb_eps:nn + { + \exp_args:Ne \__kernel_file_name_quote:n + { + \l__graphics_backend_name_str + - \str_tail:N \l__graphics_backend_ext_str + -converted-to.pdf + } + } + {#1} + } + \cs_new_eq:NN \__graphics_backend_getbb_ps:n \__graphics_backend_getbb_eps:n + \cs_new_protected:Npn \__graphics_backend_getbb_eps:nn #1#2 + { + \file_compare_timestamp:nNnT {#2} > {#1} + { + \sys_shell_now:n + { repstopdf ~ #2 ~ #1 } + } + \tl_set:Nn \l__graphics_final_name_str {#1} + \__graphics_backend_getbb_pdf:n {#1} + } + \cs_new_protected:Npn \__graphics_backend_include_eps:n #1 + { + \file_parse_full_name:nNNN {#1} + \l__graphics_backend_dir_str \l__graphics_backend_name_str \l__graphics_backend_ext_str + \exp_args:Ne \__graphics_backend_include_pdf:n + { + \exp_args:Ne \__kernel_file_name_quote:n + { + \l__graphics_backend_name_str + - \str_tail:N \l__graphics_backend_ext_str + -converted-to.pdf + } + } + } + \cs_new_eq:NN \__graphics_backend_include_ps:n \__graphics_backend_include_eps:n + } +\cs_new_protected:Npn \__graphics_backend_get_pagecount:n #1 + { + \tex_pdfximage:D {#1} + \int_const:cn { c__graphics_ #1 _pages_int } + { \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 ~ + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + } +\cs_new_protected:Npn \__pdf_backend_destination:nnnn #1#2#3#4 + { + \tex_pdfextension:D dest ~ + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + } +\cs_new_protected:Npn \__pdf_backend_catalog_gput:nn #1#2 + { + \tex_pdfextension:D catalog + { / #1 ~ #2 } + } +\cs_new_protected:Npn \__pdf_backend_info_gput:nn #1#2 + { + \tex_pdfextension:D info + { / #1 ~ #2 } + } +\prop_new:N \g__pdf_backend_object_prop +\cs_new_protected:Npn \__pdf_backend_object_new: + { + \tex_pdfextension:D obj ~ + reserveobjnum ~ + \int_gset:Nn \g__pdf_backend_object_int + { \tex_pdffeedback:D lastobj } + } +\cs_new:Npn \__pdf_backend_object_ref:n #1 { #1 ~ 0 ~ R } +\cs_new:Npn \__pdf_backend_object_id:n #1 {#1} +\cs_new_protected:Npn \__pdf_backend_object_write:nnn #1#2#3 + { + \tex_immediate:D \tex_pdfextension:D obj ~ + useobjnum ~ #1 + \__pdf_backend_object_write:nn {#2} {#3} + } +\cs_new:Npn \__pdf_backend_object_write:nn #1#2 + { + \str_case:nn {#1} + { + { array } { { [ ~ \exp_not:n {#2} ~ ] } } + { dict } { { << ~ \exp_not:n {#2} ~ >> } } + { fstream } + { + stream ~ attr ~ { \__pdf_exp_not_i:nn #2 } ~ + file ~ { \__pdf_exp_not_ii:nn #2 } + } + { stream } + { + stream ~ attr ~ { \__pdf_exp_not_i:nn #2 } ~ + { \__pdf_exp_not_ii:nn #2 } + } + } + } +\cs_generate_variant:Nn \__pdf_backend_object_write:nnn { nne } +\cs_new:Npn \__pdf_exp_not_i:nn #1#2 { \exp_not:n {#1} } +\cs_new:Npn \__pdf_exp_not_ii:nn #1#2 { \exp_not:n {#2} } +\cs_new_protected:Npn \__pdf_backend_object_now:nn #1#2 + { + \tex_immediate:D \tex_pdfextension:D obj ~ + \__pdf_backend_object_write:nn {#1} {#2} + } +\cs_generate_variant:Nn \__pdf_backend_object_now:nn { ne } +\cs_new:Npe \__pdf_backend_object_last: + { + \exp_not:N \int_value:w + \exp_not:N \tex_pdffeedback:D lastobj ~ + \c_space_tl 0 ~ R + } +\cs_new:Npe \__pdf_backend_pageobject_ref:n #1 + { + \exp_not:N \int_value:w + \exp_not:N \tex_pdffeedback:D pageref + \c_space_tl #1 \c_space_tl \c_space_tl \c_space_tl 0 ~ R + } +\cs_new_protected:Npn \__pdf_backend_compresslevel:n #1 + { + \tex_global:D + \tex_pdfvariable:D compresslevel + \int_value:w \int_eval:n {#1} \scan_stop: + } +\cs_new_protected:Npn \__pdf_backend_compress_objects:n #1 + { + \bool_if:nTF {#1} + { \__pdf_backend_objcompresslevel:n { 2 } } + { \__pdf_backend_objcompresslevel:n { 0 } } + } +\cs_new_protected:Npn \__pdf_backend_objcompresslevel:n #1 + { + \tex_global:D + \tex_pdfvariable:D objcompresslevel + #1 \scan_stop: + } +\cs_new_protected:Npe \__pdf_backend_version_major_gset:n #1 + { + \int_compare:nNnT \tex_luatexversion:D > { 106 } + { + \exp_not:N \tex_global:D \tex_pdfvariable:D majorversion + \exp_not:N \int_eval:n {#1} \scan_stop: + } + } +\cs_new_protected:Npn \__pdf_backend_version_minor_gset:n #1 + { + \tex_global:D + \tex_pdfvariable:D minorversion + \int_eval:n {#1} \scan_stop: + } +\cs_new:Npe \__pdf_backend_version_major: + { + \int_compare:nNnTF \tex_luatexversion:D > { 106 } + { \exp_not:N \tex_the:D \tex_pdfvariable:D majorversion } + { 1 } + } +\cs_new:Npn \__pdf_backend_version_minor: + { + \tex_the:D + \tex_pdfvariable:D minorversion + } +\cs_new_protected:Npn \__pdf_backend_bdc:nn #1#2 + { \__kernel_backend_literal_page:n { /#1 ~ #2 ~ BDC } } +\cs_new_protected:Npn \__pdf_backend_emc: + { \__kernel_backend_literal_page:n { EMC } } +\cs_new_protected:Npn \__pdf_backend_pagesize_gset:nn #1#2 + { + \dim_gset:Nn \tex_pagewidth:D {#1} + \dim_gset:Nn \tex_pageheight:D {#2} + } +%% File: l3backend-opacity.dtx +\bool_lazy_and:nnT + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \__kernel_color_backend_stack_init:Nnn \c__opacity_backend_stack_int + { page ~ direct } { /opacity 1 ~ gs } + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity 1 } { << /ca ~ 1 /CA ~ 1 >> } + } +\tl_new:N \l__opacity_backend_fill_tl +\tl_new:N \l__opacity_backend_stroke_tl +\tl_set:Nn \l__opacity_backend_fill_tl { 1 } +\tl_set:Nn \l__opacity_backend_stroke_tl { 1 } +\cs_new_protected:Npn \__opacity_backend_select:n #1 + { + \tl_set:Nn \l__opacity_backend_fill_tl {#1} + \tl_set:Nn \l__opacity_backend_stroke_tl {#1} + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity #1 } + { << /ca ~ #1 /CA ~ #1 >> } + \__kernel_color_backend_stack_push:nn \c__opacity_backend_stack_int + { /opacity #1 ~ gs } + \group_insert_after:N \__opacity_backend_reset: + } +\cs_new_protected:Npn \__opacity_backend_reset: + { + \__kernel_color_backend_stack_pop:n \c__opacity_backend_stack_int + } +\cs_new_protected:Npn \__opacity_backend_fill:n #1 + { + \exp_args:Nno \__opacity_backend_fill_stroke:nn + { #1 } + { \l__opacity_backend_stroke_tl } + } +\cs_new_protected:Npn \__opacity_backend_stroke:n #1 + { + \exp_args:No \__opacity_backend_fill_stroke:nn + { \l__opacity_backend_fill_tl } + { #1 } + } +\cs_new_protected:Npn \__opacity_backend_fill_stroke:nn #1#2 + { + \str_if_eq:nnTF {#1} {#2} + { \__opacity_backend_select:n {#1} } + { + \tl_set:Nn \l__opacity_backend_fill_tl {#1} + \tl_set:Nn \l__opacity_backend_stroke_tl {#2} + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity.fill #1 } + { << /ca ~ #1 >> } + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity.stroke #2 } + { << /CA ~ #2 >> } + \__kernel_color_backend_stack_push:nn \c__opacity_backend_stack_int + { /opacity.fill #1 ~ gs /opacity.stroke #2 ~ gs } + \group_insert_after:N \__opacity_backend_reset: + } + } +\bool_lazy_and:nnF + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \cs_gset_protected:Npn \__opacity_backend_select:n #1 { } + \cs_gset_protected:Npn \__opacity_backend_fill_stroke:nn #1#2 { } + } +%% +%% +%% End of file `l3backend-luatex.def'. diff --git a/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.lua b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.lua new file mode 100644 index 00000000000..ef34f055780 --- /dev/null +++ b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-luatex.lua @@ -0,0 +1,125 @@ +-- +-- This is file `l3backend-luatex.lua', +-- generated with the docstrip utility. +-- +-- The original source files were: +-- +-- l3backend-color.dtx (with options: `lua') +-- l3backend-opacity.dtx (with options: `lua') +-- +-- Copyright (C) 2023,2024 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. +-- +-- File: l3backend-color.dtx +local l = lpeg +local spaces = l.P' '^0 +local digit16 = l.R('09', 'af', 'AF') + +local octet = digit16 * digit16 / function(s) + return string.format('%.3g ', tonumber(s, 16) / 255) +end + +if luaotfload and luaotfload.set_transparent_colorstack then + local htmlcolor = l.Cs(octet * octet * octet * -1 * l.Cc'rg') + local color_export = { + token.create'tex_endlocalcontrol:D', + token.create'tex_hpack:D', + token.new(0, 1), + token.create'color_export:nnN', + token.new(0, 1), + '', + token.new(0, 2), + token.new(0, 1), + 'backend', + token.new(0, 2), + token.create'l_tmpa_tl', + token.create'exp_after:wN', + token.create'__color_select:nn', + token.create'l_tmpa_tl', + token.new(0, 2), + } + local group_end = token.create'group_end:' + local value = (1 - l.P'}')^0 + luatexbase.add_to_callback('luaotfload.parse_color', function (value) + local html = htmlcolor:match(value) + if html then return html end + + local l3color_prop = token.get_macro(string.format('l__color_named_%s_prop', value)) + if l3color_prop == nil or l3color_prop == '' then + local legacy_color_macro = token.create(string.format('\\color@%s', value)) + if legacy_color_macro.cmdname ~= 'undefined_cs' then + token.put_next(legacy_color_macro) + return token.scan_argument() + end + end + + tex.runtoks(function() + token.get_next() + color_export[6] = value + tex.sprint(-2, color_export) + end) + local list = token.scan_list() + if not list.head or list.head.next + or list.head.subtype ~= node.subtype'pdf_colorstack' then + error'Unexpected backend behavior' + end + local cmd = list.head.data + node.free(list) + return cmd + end, 'l3color') +end +-- File: l3backend-opacity.dtx +local pdfmanagement_active do + local pdfmanagement_if_active_p = token.create'pdfmanagement_if_active_p:' + local cmd = pdfmanagement_if_active_p.cmdname + if cmd == 'undefined_cs' then + pdfmanagement_active = false + else + token.put_next(pdfmanagement_if_active_p) + pdfmanagement_active = token.scan_int() ~= 0 + end +end + +if pdfmanagement_active and luaotfload and luaotfload.set_transparent_colorstack then + luaotfload.set_transparent_colorstack(function() return token.create'c__opacity_backend_stack_int'.index end) + + local transparent_register = { + token.create'pdfmanagement_add:nnn', + token.new(0, 1), + 'Page/Resources/ExtGState', + token.new(0, 2), + token.new(0, 1), + '', + token.new(0, 2), + token.new(0, 1), + '<>', + token.new(0, 2), + } + luatexbase.add_to_callback('luaotfload.parse_transparent', function(value) + value = (octet * -1):match(value) + if not value then + tex.error'Invalid transparency value' + return + end + value = value:sub(1, -2) + local result = 'opacity' .. value + tex.runtoks(function() + transparent_register[6], transparent_register[10], transparent_register[12] = result, value, value + tex.sprint(-2, transparent_register) + end) + return '/' .. result .. ' gs' + end, 'l3opacity') +end diff --git a/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-pdftex.def b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-pdftex.def new file mode 100644 index 00000000000..3c51094bbc8 --- /dev/null +++ b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-pdftex.def @@ -0,0 +1,902 @@ +%% +%% This is file `l3backend-pdftex.def', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3backend-basics.dtx (with options: `package,pdftex') +%% l3backend-color.dtx (with options: `package,pdftex') +%% l3backend-box.dtx (with options: `package,pdftex') +%% l3backend-draw.dtx (with options: `package,pdftex') +%% l3backend-graphics.dtx (with options: `package,pdftex') +%% l3backend-pdf.dtx (with options: `package,pdftex') +%% l3backend-opacity.dtx (with options: `package,pdftex') +%% +%% Copyright (C) 2019-2024 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. +%% +%% File: l3backend-basics.dtx +\ProvidesExplFile + {l3backend-pdftex.def}{2024-04-11}{} + {L3 backend support: PDF output (pdfTeX)} +\cs_if_exist:NTF \__kernel_dependency_version_check:nn + { + \__kernel_dependency_version_check:nn {2023-10-10} + {l3backend-pdftex.def} + } + { + \cs_if_exist_use:cF { @latex@error } { \errmessage } + { + Mismatched~LaTeX~support~files~detected. \MessageBreak + Loading~aborted! + } + { \use:c { @ehd } } + \tex_endinput:D + } +\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} } } +\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 } +\cs_new_protected:Npn \__kernel_backend_literal_pdf:n #1 + { + \tex_pdfliteral:D + { \exp_not:n {#1} } + } +\cs_generate_variant:Nn \__kernel_backend_literal_pdf:n { e } +\cs_new_protected:Npn \__kernel_backend_literal_page:n #1 + { + \tex_pdfliteral:D + page { \exp_not:n {#1} } + } +\cs_new_protected:Npn \__kernel_backend_literal_page:e #1 + { + \tex_pdfliteral:D + page {#1} + } +\cs_new_protected:Npn \__kernel_backend_scope_begin: + { + \tex_pdfsave:D + } +\cs_new_protected:Npn \__kernel_backend_scope_end: + { + \tex_pdfrestore:D + } +\cs_new_protected:Npn \__kernel_backend_matrix:n #1 + { + \tex_pdfsetmatrix:D + { \exp_not:n {#1} } + } +\cs_generate_variant:Nn \__kernel_backend_matrix:n { e } +%% 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 + { + \int_const:Nn #1 + { + \tex_pdfcolorstackinit:D + \tl_if_blank:nF {#2} { #2 ~ } + {#3} + } + } +\cs_new_protected:Npn \__kernel_color_backend_stack_push:nn #1#2 + { + \tex_pdfcolorstack:D + \int_eval:n {#1} ~ push ~ {#2} + } +\cs_new_protected:Npn \__kernel_color_backend_stack_pop:n #1 + { + \tex_pdfcolorstack:D + \int_eval:n {#1} ~ pop \scan_stop: + } +\tl_new:N \l__color_backend_fill_tl +\tl_new:N \l__color_backend_stroke_tl +\tl_set:Nn \l__color_backend_fill_tl { 0 ~ g } +\tl_set:Nn \l__color_backend_stroke_tl { 0 ~ G } +\cs_new_protected:Npn \__color_backend_select_cmyk:n #1 + { \__color_backend_select:nn { #1 ~ k } { #1 ~ K } } +\cs_new_protected:Npn \__color_backend_select_gray:n #1 + { \__color_backend_select:nn { #1 ~ g } { #1 ~ G } } +\cs_new_protected:Npn \__color_backend_select_rgb:n #1 + { \__color_backend_select:nn { #1 ~ rg } { #1 ~ RG } } +\cs_new_protected:Npn \__color_backend_select:nn #1#2 + { + \tl_set:Nn \l__color_backend_fill_tl {#1} + \tl_set:Nn \l__color_backend_stroke_tl {#2} + \__kernel_color_backend_stack_push:nn \l__color_backend_stack_int { #1 ~ #2 } + } +\cs_new_protected:Npn \__color_backend_reset: + { \__kernel_color_backend_stack_pop:n \l__color_backend_stack_int } +\prop_new:N \g__color_backend_colorant_prop +\cs_new:Npe \__color_backend_devicen_colorants:n #1 + { + \exp_not:N \tl_if_blank:nF {#1} + { + \c_space_tl + << ~ + /Colorants ~ + << ~ + \exp_not:N \__color_backend_devicen_colorants:w #1 ~ + \exp_not:N \q_recursion_tail \c_space_tl + \exp_not:N \q_recursion_stop + >> ~ + >> + } + } +\cs_new:Npn \__color_backend_devicen_colorants:w #1 ~ + { + \quark_if_recursion_tail_stop:n {#1} + \prop_if_in:NnT \g__color_backend_colorant_prop {#1} + { + #1 ~ + \prop_item:Nn \g__color_backend_colorant_prop {#1} ~ + } + \__color_backend_devicen_colorants:w + } +\cs_new_protected:Npn \__color_backend_select_separation:nn #1#2 + { \__color_backend_select:nn { /#1 ~ cs ~ #2 ~ scn } { /#1 ~ CS ~ #2 ~ SCN } } +\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn +\cs_new_eq:NN \__color_backend_select_iccbased:nn \__color_backend_select_separation:nn +\cs_new_protected:Npn \__color_backend_init_resource:n #1 + { + \bool_lazy_and:nnT + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \use:e + { + \pdfmanagement_add:nnn + { Page / Resources / ColorSpace } + { #1 } + { \pdf_object_ref_last: } + } + } + } +\cs_new_protected:Npn \__color_backend_separation_init:nnnnn #1#2#3#4#5 + { + \pdf_object_unnamed_write:ne { dict } + { + /FunctionType ~ 2 + /Domain ~ [0 ~ 1] + \tl_if_blank:nF {#3} { /Range ~ [#3] } + /C0 ~ [#4] ~ + /C1 ~ [#5] /N ~ 1 + } + \exp_args:Ne \__color_backend_separation_init:nn + { \str_convert_pdfname:n {#1} } {#2} + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new_protected:Npn \__color_backend_separation_init:nn #1#2 + { + \use:e + { + \pdf_object_new:n { color \int_use:N \g__color_model_int } + \pdf_object_write:nnn { color \int_use:N \g__color_model_int } { array } + { /Separation /#1 ~ #2 ~ \pdf_object_ref_last: } + } + \prop_gput:Nne \g__color_backend_colorant_prop { /#1 } + { \pdf_object_ref_last: } + } +\cs_new_protected:Npn \__color_backend_separation_init_CIELAB:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_illuminant_CIELAB_ #1 } + { + \pdf_object_new:n { __color_illuminant_CIELAB_ #1 } + \pdf_object_write:nne { __color_illuminant_CIELAB_ #1 } { array } + { + /Lab ~ + << + /WhitePoint ~ + [ \tl_use:c { c__color_model_whitepoint_CIELAB_ #1 _tl } ] + /Range ~ [ \c__color_model_range_CIELAB_tl ] + >> + } + } + \__color_backend_separation_init:nnnnn + {#2} + { \pdf_object_ref:n { __color_illuminant_CIELAB_ #1 } } + { \c__color_model_range_CIELAB_tl } + { 100 ~ 0 ~ 0 } + {#3} + } +\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3 + { + \pdf_object_unnamed_write:ne { stream } + { + { + /FunctionType ~ 4 ~ + /Domain ~ + [ ~ + \prg_replicate:nn + { 0 \__color_backend_devicen_init:w #1 ~ \s__color_stop } + { 0 ~ 1 ~ } + ] ~ + /Range ~ + [ ~ + \str_case:nn {#2} + { + { /DeviceCMYK } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 } + { /DeviceGray } { 0 ~ 1 } + { /DeviceRGB } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 } + } ~ + ] + } + { {#3} } + } + \use:e + { + \pdf_object_new:n { color \int_use:N \g__color_model_int } + \pdf_object_write:nnn { color \int_use:N \g__color_model_int } { array } + { + /DeviceN ~ + [ ~ #1 ~ ] ~ + #2 ~ + \pdf_object_ref_last: + \__color_backend_devicen_colorants:n {#1} + } + } + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new:Npn \__color_backend_devicen_init:w #1 ~ #2 \s__color_stop + { + + 1 + \tl_if_blank:nF {#2} + { \__color_backend_devicen_init:w #2 \s__color_stop } + } +\cs_new_protected:Npn \__color_backend_iccbased_init:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_icc_ #1 } + { + \pdf_object_new:n { __color_icc_ #1 } + \pdf_object_write:nne { __color_icc_ #1 } { fstream } + { + { + /N ~ \exp_not:n { #2 } ~ + \tl_if_empty:nF { #3 } { /Range~[ #3 ] } + } + {#1} + } + } + \pdf_object_unnamed_write:ne { array } + { /ICCBased ~ \pdf_object_ref:n { __color_icc_ #1 } } + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new_protected:Npn \__color_backend_iccbased_device:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_icc_ #1 } + { + \pdf_object_new:n { __color_icc_ #1 } + \pdf_object_write:nnn { __color_icc_ #1 } { fstream } + { + { /N ~ #3 } + {#1} + } + } + \pdf_object_unnamed_write:ne { array } + { /ICCBased ~ \pdf_object_ref:n { __color_icc_ #1 } } + \__color_backend_init_resource:n { Default #2 } + } +\cs_new_protected:Npn \__color_backend_fill_cmyk:n #1 + { \__color_backend_fill:n { #1 ~ k } } +\cs_new_protected:Npn \__color_backend_fill_gray:n #1 + { \__color_backend_fill:n { #1 ~ g } } +\cs_new_protected:Npn \__color_backend_fill_rgb:n #1 + { \__color_backend_fill:n { #1 ~ rg } } +\cs_new_protected:Npn \__color_backend_fill:n #1 + { + \tl_set:Nn \l__color_backend_fill_tl {#1} + \__kernel_color_backend_stack_push:nn \l__color_backend_stack_int + { #1 ~ \l__color_backend_stroke_tl } + } +\cs_new_protected:Npn \__color_backend_stroke_cmyk:n #1 + { \__color_backend_stroke:n { #1 ~ K } } +\cs_new_protected:Npn \__color_backend_stroke_gray:n #1 + { \__color_backend_stroke:n { #1 ~ G } } +\cs_new_protected:Npn \__color_backend_stroke_rgb:n #1 + { \__color_backend_stroke:n { #1 ~ RG } } +\cs_new_protected:Npn \__color_backend_stroke:n #1 + { + \tl_set:Nn \l__color_backend_stroke_tl {#1} + \__kernel_color_backend_stack_push:nn \l__color_backend_stack_int + { \l__color_backend_fill_tl \c_space_tl #1 } + } +\cs_new_protected:Npn \__color_backend_fill_separation:nn #1#2 + { \__color_backend_fill:n { /#1 ~ cs ~ #2 ~ scn } } +\cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2 + { \__color_backend_stroke:n { /#1 ~ CS ~ #2 ~ SCN } } +\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn +\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn +\cs_new_eq:NN \__color_backend_fill_reset: \__color_backend_reset: +\cs_new_eq:NN \__color_backend_stroke_reset: \__color_backend_reset: +%% File: l3backend-box.dtx +\cs_new_protected:Npn \__box_backend_clip:N #1 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal_pdf:e + { + 0~ + \dim_to_decimal_in_bp:n { -\box_dp:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~ + re~W~n + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + \skip_horizontal:n { \box_wd:N #1 } + } +\cs_new_protected:Npn \__box_backend_rotate:Nn #1#2 + { \exp_args:NNf \__box_backend_rotate_aux:Nn #1 { \fp_eval:n {#2} } } +\cs_new_protected:Npn \__box_backend_rotate_aux:Nn #1#2 + { + \__kernel_backend_scope_begin: + \box_set_wd:Nn #1 { 0pt } + \fp_set:Nn \l__box_backend_cos_fp { round ( cosd ( #2 ) , 5 ) } + \fp_compare:nNnT \l__box_backend_cos_fp = \c_zero_fp + { \fp_zero:N \l__box_backend_cos_fp } + \fp_set:Nn \l__box_backend_sin_fp { round ( sind ( #2 ) , 5 ) } + \__kernel_backend_matrix:e + { + \fp_use:N \l__box_backend_cos_fp \c_space_tl + \fp_compare:nNnTF \l__box_backend_sin_fp = \c_zero_fp + { 0~0 } + { + \fp_use:N \l__box_backend_sin_fp + \c_space_tl + \fp_eval:n { -\l__box_backend_sin_fp } + } + \c_space_tl + \fp_use:N \l__box_backend_cos_fp + } + \box_use:N #1 + \__kernel_backend_scope_end: + } +\fp_new:N \l__box_backend_cos_fp +\fp_new:N \l__box_backend_sin_fp +\cs_new_protected:Npn \__box_backend_scale:Nnn #1#2#3 + { + \__kernel_backend_scope_begin: + \__kernel_backend_matrix:e + { + \fp_eval:n { round ( #2 , 5 ) } ~ + 0~0~ + \fp_eval:n { round ( #3 , 5 ) } + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +%% 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_protected:Npn \__draw_backend_begin: + { \__draw_backend_scope_begin: } +\cs_new_protected:Npn \__draw_backend_end: + { \__draw_backend_scope_end: } +\cs_new_eq:NN \__draw_backend_scope_begin: \__kernel_backend_scope_begin: +\cs_new_eq:NN \__draw_backend_scope_end: \__kernel_backend_scope_end: +\cs_new_protected:Npn \__draw_backend_moveto:nn #1#2 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ m } + } +\cs_new_protected:Npn \__draw_backend_lineto:nn #1#2 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ l } + } +\cs_new_protected:Npn \__draw_backend_curveto:nnnnnn #1#2#3#4#5#6 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~ + c + } + } +\cs_new_protected:Npn \__draw_backend_rectangle:nnnn #1#2#3#4 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + re + } + } +\cs_new_protected:Npn \__draw_backend_evenodd_rule: + { \bool_gset_true:N \g__draw_draw_eor_bool } +\cs_new_protected:Npn \__draw_backend_nonzero_rule: + { \bool_gset_false:N \g__draw_draw_eor_bool } +\bool_new:N \g__draw_draw_eor_bool +\cs_new_protected:Npn \__draw_backend_closepath: + { \__draw_backend_literal:n { h } } +\cs_new_protected:Npn \__draw_backend_stroke: + { \__draw_backend_literal:n { S } } +\cs_new_protected:Npn \__draw_backend_closestroke: + { \__draw_backend_literal:n { s } } +\cs_new_protected:Npn \__draw_backend_fill: + { + \__draw_backend_literal:e + { f \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_fillstroke: + { + \__draw_backend_literal:e + { B \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_clip: + { + \__draw_backend_literal:e + { W \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_discardpath: + { \__draw_backend_literal:n { n } } +\cs_new_protected:Npn \__draw_backend_dash_pattern:nn #1#2 + { + \__draw_backend_literal:e + { + [ + \exp_args:Nf \use:n + { \clist_map_function:nN {#1} \__draw_backend_dash:n } + ] ~ + \dim_to_decimal_in_bp:n {#2} ~ d + } + } +\cs_new:Npn \__draw_backend_dash:n #1 + { ~ \dim_to_decimal_in_bp:n {#1} } +\cs_new_protected:Npn \__draw_backend_linewidth:n #1 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ w } + } +\cs_new_protected:Npn \__draw_backend_miterlimit:n #1 + { \__draw_backend_literal:e { #1 ~ M } } +\cs_new_protected:Npn \__draw_backend_cap_butt: + { \__draw_backend_literal:n { 0 ~ J } } +\cs_new_protected:Npn \__draw_backend_cap_round: + { \__draw_backend_literal:n { 1 ~ J } } +\cs_new_protected:Npn \__draw_backend_cap_rectangle: + { \__draw_backend_literal:n { 2 ~ J } } +\cs_new_protected:Npn \__draw_backend_join_miter: + { \__draw_backend_literal:n { 0 ~ j } } +\cs_new_protected:Npn \__draw_backend_join_round: + { \__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 + { + \__kernel_backend_matrix:n { #1 ~ #2 ~ #3 ~ #4 } + } +\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} + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +%% File: l3backend-graphics.dtx +\cs_new_protected:Npn \__graphics_backend_loaded:n #1 + { + \cs_if_exist:NTF \hook_gput_code:nnn + { + \hook_gput_code:nnn + { package / l3graphics / after } + { backend } + {#1} + } + {#1} + } +\__graphics_backend_loaded:n + { + \seq_set_from_clist:Nn + \l_graphics_search_ext_seq + { .pdf , .eps , .ps , .png , .jpg , .jpeg } + } +\tl_new:N \l__graphics_attr_tl +\cs_new_protected:Npn \__graphics_backend_getbb_jpg:n #1 + { + \int_zero:N \l__graphics_page_int + \tl_clear:N \l__graphics_pagebox_tl + \tl_set:Ne \l__graphics_attr_tl + { + \tl_if_empty:NF \l__graphics_decodearray_str + { :D \l__graphics_decodearray_str } + \bool_if:NT \l__graphics_interpolate_bool + { :I } + \str_if_empty:NF \l__graphics_pdf_str + { :X \l__graphics_pdf_str } + } + \__graphics_backend_getbb_auxi:n {#1} + } +\cs_new_eq:NN \__graphics_backend_getbb_jpeg:n \__graphics_backend_getbb_jpg:n +\cs_new_eq:NN \__graphics_backend_getbb_png:n \__graphics_backend_getbb_jpg:n +\cs_new_protected:Npn \__graphics_backend_getbb_pdf:n #1 + { + \tl_clear:N \l__graphics_decodearray_str + \bool_set_false:N \l__graphics_interpolate_bool + \tl_set:Ne \l__graphics_attr_tl + { + : \l__graphics_pagebox_tl + \int_compare:nNnT \l__graphics_page_int > 1 + { :P \int_use:N \l__graphics_page_int } + \str_if_empty:NF \l__graphics_pdf_str + { :X \l__graphics_pdf_str } + } + \__graphics_backend_getbb_auxi:n {#1} + } +\cs_new_protected:Npn \__graphics_backend_getbb_auxi:n #1 + { + \__graphics_bb_restore:eF { #1 \l__graphics_attr_tl } + { \__graphics_backend_getbb_auxii:n {#1} } + } +\cs_new_protected:Npn \__graphics_backend_getbb_auxii:n #1 + { + \exp_args:Ne \__graphics_backend_getbb_auxiii:n + { \__graphics_backend_dequote:w #1 " #1 " \s__graphics_stop } + \int_const:cn { c__graphics_ #1 \l__graphics_attr_tl _int } + { \tex_the:D \tex_pdflastximage:D } + \__graphics_bb_save:e { #1 \l__graphics_attr_tl } + } +\cs_new_protected:Npn \__graphics_backend_getbb_auxiii:n #1 + { + \tex_immediate:D \tex_pdfximage:D + \bool_lazy_any:nT + { + { \l__graphics_interpolate_bool } + { ! \tl_if_empty_p:N \l__graphics_decodearray_str } + { ! \str_if_empty_p:N \l__graphics_pdf_str } + } + { + attr ~ + { + \tl_if_empty:NF \l__graphics_decodearray_str + { /Decode~[ \l__graphics_decodearray_str ] } + \bool_if:NT \l__graphics_interpolate_bool + { /Interpolate~true } + \l__graphics_pdf_str + } + } + \int_compare:nNnT \l__graphics_page_int > 0 + { page ~ \int_use:N \l__graphics_page_int } + \tl_if_empty:NF \l__graphics_pagebox_tl + { \l__graphics_pagebox_tl } + {#1} + \hbox_set:Nn \l__graphics_internal_box + { \tex_pdfrefximage:D \tex_pdflastximage:D } + \dim_set:Nn \l__graphics_urx_dim { \box_wd:N \l__graphics_internal_box } + \dim_set:Nn \l__graphics_ury_dim { \box_ht:N \l__graphics_internal_box } + } +\cs_new:Npn \__graphics_backend_dequote:w #1 " #2 " #3 \s__graphics_stop {#2} +\cs_new_protected:Npn \__graphics_backend_include_jpg:n #1 + { + \tex_pdfrefximage:D + \int_use:c { c__graphics_ #1 \l__graphics_attr_tl _int } + } +\cs_new_eq:NN \__graphics_backend_include_jpeg:n \__graphics_backend_include_jpg:n +\cs_new_eq:NN \__graphics_backend_include_pdf:n \__graphics_backend_include_jpg:n +\cs_new_eq:NN \__graphics_backend_include_png:n \__graphics_backend_include_jpg:n +\sys_if_shell:T + { + \str_new:N \l__graphics_backend_dir_str + \str_new:N \l__graphics_backend_name_str + \str_new:N \l__graphics_backend_ext_str + \cs_new_protected:Npn \__graphics_backend_getbb_eps:n #1 + { + \file_parse_full_name:nNNN {#1} + \l__graphics_backend_dir_str + \l__graphics_backend_name_str + \l__graphics_backend_ext_str + \exp_args:Ne \__graphics_backend_getbb_eps:nn + { + \exp_args:Ne \__kernel_file_name_quote:n + { + \l__graphics_backend_name_str + - \str_tail:N \l__graphics_backend_ext_str + -converted-to.pdf + } + } + {#1} + } + \cs_new_eq:NN \__graphics_backend_getbb_ps:n \__graphics_backend_getbb_eps:n + \cs_new_protected:Npn \__graphics_backend_getbb_eps:nn #1#2 + { + \file_compare_timestamp:nNnT {#2} > {#1} + { + \sys_shell_now:n + { repstopdf ~ #2 ~ #1 } + } + \tl_set:Nn \l__graphics_final_name_str {#1} + \__graphics_backend_getbb_pdf:n {#1} + } + \cs_new_protected:Npn \__graphics_backend_include_eps:n #1 + { + \file_parse_full_name:nNNN {#1} + \l__graphics_backend_dir_str \l__graphics_backend_name_str \l__graphics_backend_ext_str + \exp_args:Ne \__graphics_backend_include_pdf:n + { + \exp_args:Ne \__kernel_file_name_quote:n + { + \l__graphics_backend_name_str + - \str_tail:N \l__graphics_backend_ext_str + -converted-to.pdf + } + } + } + \cs_new_eq:NN \__graphics_backend_include_ps:n \__graphics_backend_include_eps:n + } +\cs_new_protected:Npn \__graphics_backend_get_pagecount:n #1 + { + \tex_pdfximage:D {#1} + \int_const:cn { c__graphics_ #1 _pages_int } + { \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 + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + } +\cs_new_protected:Npn \__pdf_backend_destination:nnnn #1#2#3#4 + { + \tex_pdfdest:D + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + } +\cs_new_protected:Npn \__pdf_backend_catalog_gput:nn #1#2 + { + \tex_pdfcatalog:D + { / #1 ~ #2 } + } +\cs_new_protected:Npn \__pdf_backend_info_gput:nn #1#2 + { + \tex_pdfinfo:D + { / #1 ~ #2 } + } +\prop_new:N \g__pdf_backend_object_prop +\cs_new_protected:Npn \__pdf_backend_object_new: + { + \tex_pdfobj:D + reserveobjnum ~ + \int_gset:Nn \g__pdf_backend_object_int + { \tex_pdflastobj:D } + } +\cs_new:Npn \__pdf_backend_object_ref:n #1 { #1 ~ 0 ~ R } +\cs_new:Npn \__pdf_backend_object_id:n #1 {#1} +\cs_new_protected:Npn \__pdf_backend_object_write:nnn #1#2#3 + { + \tex_immediate:D \tex_pdfobj:D + useobjnum ~ #1 + \__pdf_backend_object_write:nn {#2} {#3} + } +\cs_new:Npn \__pdf_backend_object_write:nn #1#2 + { + \str_case:nn {#1} + { + { array } { { [ ~ \exp_not:n {#2} ~ ] } } + { dict } { { << ~ \exp_not:n {#2} ~ >> } } + { fstream } + { + stream ~ attr ~ { \__pdf_exp_not_i:nn #2 } ~ + file ~ { \__pdf_exp_not_ii:nn #2 } + } + { stream } + { + stream ~ attr ~ { \__pdf_exp_not_i:nn #2 } ~ + { \__pdf_exp_not_ii:nn #2 } + } + } + } +\cs_generate_variant:Nn \__pdf_backend_object_write:nnn { nne } +\cs_new:Npn \__pdf_exp_not_i:nn #1#2 { \exp_not:n {#1} } +\cs_new:Npn \__pdf_exp_not_ii:nn #1#2 { \exp_not:n {#2} } +\cs_new_protected:Npn \__pdf_backend_object_now:nn #1#2 + { + \tex_immediate:D \tex_pdfobj:D + \__pdf_backend_object_write:nn {#1} {#2} + } +\cs_generate_variant:Nn \__pdf_backend_object_now:nn { ne } +\cs_new:Npe \__pdf_backend_object_last: + { + \exp_not:N \int_value:w + \exp_not:N \tex_pdflastobj:D + \c_space_tl 0 ~ R + } +\cs_new:Npe \__pdf_backend_pageobject_ref:n #1 + { + \exp_not:N \int_value:w + \exp_not:N \tex_pdfpageref:D + \c_space_tl #1 \c_space_tl \c_space_tl \c_space_tl 0 ~ R + } +\cs_new_protected:Npn \__pdf_backend_compresslevel:n #1 + { + \tex_global:D + \tex_pdfcompresslevel:D + \int_value:w \int_eval:n {#1} \scan_stop: + } +\cs_new_protected:Npn \__pdf_backend_compress_objects:n #1 + { + \bool_if:nTF {#1} + { \__pdf_backend_objcompresslevel:n { 2 } } + { \__pdf_backend_objcompresslevel:n { 0 } } + } +\cs_new_protected:Npn \__pdf_backend_objcompresslevel:n #1 + { + \tex_global:D + \tex_pdfobjcompresslevel:D + #1 \scan_stop: + } +\cs_new_protected:Npe \__pdf_backend_version_major_gset:n #1 + { + \cs_if_exist:NT \tex_pdfmajorversion:D + { + \exp_not:N \tex_global:D \tex_pdfmajorversion:D + \exp_not:N \int_eval:n {#1} \scan_stop: + } + } +\cs_new_protected:Npn \__pdf_backend_version_minor_gset:n #1 + { + \tex_global:D + \tex_pdfminorversion:D + \int_eval:n {#1} \scan_stop: + } +\cs_new:Npe \__pdf_backend_version_major: + { + \cs_if_exist:NTF \tex_pdfmajorversion:D + { \exp_not:N \tex_the:D \tex_pdfmajorversion:D } + { 1 } + } +\cs_new:Npn \__pdf_backend_version_minor: + { + \tex_the:D + \tex_pdfminorversion:D + } +\cs_new_protected:Npn \__pdf_backend_bdc:nn #1#2 + { \__kernel_backend_literal_page:n { /#1 ~ #2 ~ BDC } } +\cs_new_protected:Npn \__pdf_backend_emc: + { \__kernel_backend_literal_page:n { EMC } } +\cs_new_protected:Npn \__pdf_backend_pagesize_gset:nn #1#2 + { + \dim_gset:Nn \tex_pagewidth:D {#1} + \dim_gset:Nn \tex_pageheight:D {#2} + } +%% File: l3backend-opacity.dtx +\bool_lazy_and:nnT + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \__kernel_color_backend_stack_init:Nnn \c__opacity_backend_stack_int + { page ~ direct } { /opacity 1 ~ gs } + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity 1 } { << /ca ~ 1 /CA ~ 1 >> } + } +\tl_new:N \l__opacity_backend_fill_tl +\tl_new:N \l__opacity_backend_stroke_tl +\tl_set:Nn \l__opacity_backend_fill_tl { 1 } +\tl_set:Nn \l__opacity_backend_stroke_tl { 1 } +\cs_new_protected:Npn \__opacity_backend_select:n #1 + { + \tl_set:Nn \l__opacity_backend_fill_tl {#1} + \tl_set:Nn \l__opacity_backend_stroke_tl {#1} + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity #1 } + { << /ca ~ #1 /CA ~ #1 >> } + \__kernel_color_backend_stack_push:nn \c__opacity_backend_stack_int + { /opacity #1 ~ gs } + \group_insert_after:N \__opacity_backend_reset: + } +\cs_new_protected:Npn \__opacity_backend_reset: + { + \__kernel_color_backend_stack_pop:n \c__opacity_backend_stack_int + } +\cs_new_protected:Npn \__opacity_backend_fill:n #1 + { + \exp_args:Nno \__opacity_backend_fill_stroke:nn + { #1 } + { \l__opacity_backend_stroke_tl } + } +\cs_new_protected:Npn \__opacity_backend_stroke:n #1 + { + \exp_args:No \__opacity_backend_fill_stroke:nn + { \l__opacity_backend_fill_tl } + { #1 } + } +\cs_new_protected:Npn \__opacity_backend_fill_stroke:nn #1#2 + { + \str_if_eq:nnTF {#1} {#2} + { \__opacity_backend_select:n {#1} } + { + \tl_set:Nn \l__opacity_backend_fill_tl {#1} + \tl_set:Nn \l__opacity_backend_stroke_tl {#2} + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity.fill #1 } + { << /ca ~ #1 >> } + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity.stroke #2 } + { << /CA ~ #2 >> } + \__kernel_color_backend_stack_push:nn \c__opacity_backend_stack_int + { /opacity.fill #1 ~ gs /opacity.stroke #2 ~ gs } + \group_insert_after:N \__opacity_backend_reset: + } + } +\bool_lazy_and:nnF + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \cs_gset_protected:Npn \__opacity_backend_select:n #1 { } + \cs_gset_protected:Npn \__opacity_backend_fill_stroke:nn #1#2 { } + } +%% +%% +%% End of file `l3backend-pdftex.def'. diff --git a/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-xetex.def b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-xetex.def new file mode 100644 index 00000000000..e05725885ca --- /dev/null +++ b/Master/texmf-dist/tex/latex-dev/l3backend/l3backend-xetex.def @@ -0,0 +1,906 @@ +%% +%% This is file `l3backend-xetex.def', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3backend-basics.dtx (with options: `package,xetex') +%% l3backend-color.dtx (with options: `package,xetex') +%% l3backend-box.dtx (with options: `package,xetex') +%% l3backend-draw.dtx (with options: `package,xetex') +%% l3backend-graphics.dtx (with options: `package,xetex') +%% l3backend-pdf.dtx (with options: `package,xetex') +%% l3backend-opacity.dtx (with options: `package,xetex') +%% +%% Copyright (C) 2019-2024 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. +%% +%% File: l3backend-basics.dtx +\ProvidesExplFile + {l3backend-xetex.def}{2024-04-11}{} + {L3 backend support: XeTeX} +\cs_if_exist:NTF \__kernel_dependency_version_check:nn + { + \__kernel_dependency_version_check:nn {2023-10-10} + {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 + } +\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} } } +\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 } +\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 } +\cs_new_protected:Npn \__kernel_backend_literal_page:n #1 + { \__kernel_backend_literal:n { pdf:literal~direct~ #1 } } +\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 } } +%% File: l3backend-color.dtx +\cs_new_protected:Npn \__color_backend_select:n #1 + { \__kernel_backend_literal:n { pdf : bc ~ [ #1 ] } } +\cs_new_eq:NN \__color_backend_select_cmyk:n \__color_backend_select:n +\cs_new_eq:NN \__color_backend_select_gray:n \__color_backend_select:n +\cs_new_eq:NN \__color_backend_select_rgb:n \__color_backend_select:n +\cs_new_protected:Npn \__color_backend_reset: + { \__kernel_backend_literal:n { pdf : ec } } +\cs_new_protected:Npn \__color_backend_select_named:n #1 + { + \str_if_eq:nnTF {#1} { Black } + { \__color_backend_select_gray:n { 0 } } + { \msg_error:nnn { color } { unknown-named-color } {#1} } + } +\msg_new:nnn { color } { unknown-named-color } + { Named~color~'#1'~is~not~known. } +\prop_new:N \g__color_backend_colorant_prop +\cs_new:Npe \__color_backend_devicen_colorants:n #1 + { + \exp_not:N \tl_if_blank:nF {#1} + { + \c_space_tl + << ~ + /Colorants ~ + << ~ + \exp_not:N \__color_backend_devicen_colorants:w #1 ~ + \exp_not:N \q_recursion_tail \c_space_tl + \exp_not:N \q_recursion_stop + >> ~ + >> + } + } +\cs_new:Npn \__color_backend_devicen_colorants:w #1 ~ + { + \quark_if_recursion_tail_stop:n {#1} + \prop_if_in:NnT \g__color_backend_colorant_prop {#1} + { + #1 ~ + \prop_item:Nn \g__color_backend_colorant_prop {#1} ~ + } + \__color_backend_devicen_colorants:w + } +\cs_new_protected:Npn \__color_backend_select_separation:nn #1#2 + { \__kernel_backend_literal:e { pdf : bc ~ \pdf_object_ref:n {#1} ~ [ #2 ] } } +\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn +\cs_new_eq:NN \__color_backend_select_iccbased:nn \__color_backend_select_separation:nn +\cs_new_protected:Npn \__color_backend_init_resource:n #1 + { + } +\cs_new_protected:Npn \__color_backend_separation_init:nnnnn #1#2#3#4#5 + { + \pdf_object_unnamed_write:ne { dict } + { + /FunctionType ~ 2 + /Domain ~ [0 ~ 1] + \tl_if_blank:nF {#3} { /Range ~ [#3] } + /C0 ~ [#4] ~ + /C1 ~ [#5] /N ~ 1 + } + \exp_args:Ne \__color_backend_separation_init:nn + { \str_convert_pdfname:n {#1} } {#2} + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new_protected:Npn \__color_backend_separation_init:nn #1#2 + { + \use:e + { + \pdf_object_new:n { color \int_use:N \g__color_model_int } + \pdf_object_write:nnn { color \int_use:N \g__color_model_int } { array } + { /Separation /#1 ~ #2 ~ \pdf_object_ref_last: } + } + \prop_gput:Nne \g__color_backend_colorant_prop { /#1 } + { \pdf_object_ref_last: } + } +\cs_new_protected:Npn \__color_backend_separation_init_CIELAB:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_illuminant_CIELAB_ #1 } + { + \pdf_object_new:n { __color_illuminant_CIELAB_ #1 } + \pdf_object_write:nne { __color_illuminant_CIELAB_ #1 } { array } + { + /Lab ~ + << + /WhitePoint ~ + [ \tl_use:c { c__color_model_whitepoint_CIELAB_ #1 _tl } ] + /Range ~ [ \c__color_model_range_CIELAB_tl ] + >> + } + } + \__color_backend_separation_init:nnnnn + {#2} + { \pdf_object_ref:n { __color_illuminant_CIELAB_ #1 } } + { \c__color_model_range_CIELAB_tl } + { 100 ~ 0 ~ 0 } + {#3} + } +\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3 + { + \pdf_object_unnamed_write:ne { stream } + { + { + /FunctionType ~ 4 ~ + /Domain ~ + [ ~ + \prg_replicate:nn + { 0 \__color_backend_devicen_init:w #1 ~ \s__color_stop } + { 0 ~ 1 ~ } + ] ~ + /Range ~ + [ ~ + \str_case:nn {#2} + { + { /DeviceCMYK } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 } + { /DeviceGray } { 0 ~ 1 } + { /DeviceRGB } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 } + } ~ + ] + } + { {#3} } + } + \use:e + { + \pdf_object_new:n { color \int_use:N \g__color_model_int } + \pdf_object_write:nnn { color \int_use:N \g__color_model_int } { array } + { + /DeviceN ~ + [ ~ #1 ~ ] ~ + #2 ~ + \pdf_object_ref_last: + \__color_backend_devicen_colorants:n {#1} + } + } + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new:Npn \__color_backend_devicen_init:w #1 ~ #2 \s__color_stop + { + + 1 + \tl_if_blank:nF {#2} + { \__color_backend_devicen_init:w #2 \s__color_stop } + } +\cs_new_protected:Npn \__color_backend_iccbased_init:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_icc_ #1 } + { + \pdf_object_new:n { __color_icc_ #1 } + \pdf_object_write:nne { __color_icc_ #1 } { fstream } + { + { + /N ~ \exp_not:n { #2 } ~ + \tl_if_empty:nF { #3 } { /Range~[ #3 ] } + } + {#1} + } + } + \pdf_object_unnamed_write:ne { array } + { /ICCBased ~ \pdf_object_ref:n { __color_icc_ #1 } } + \__color_backend_init_resource:n { color \int_use:N \g__color_model_int } + } +\cs_new_protected:Npn \__color_backend_iccbased_device:nnn #1#2#3 + { + \pdf_object_if_exist:nF { __color_icc_ #1 } + { + \pdf_object_new:n { __color_icc_ #1 } + \pdf_object_write:nnn { __color_icc_ #1 } { fstream } + { + { /N ~ #3 } + {#1} + } + } + \pdf_object_unnamed_write:ne { array } + { /ICCBased ~ \pdf_object_ref:n { __color_icc_ #1 } } + \__color_backend_init_resource:n { Default #2 } + } +\cs_new_protected:Npn \__color_backend_fill:n #1 + { \__kernel_backend_literal:n { pdf : bc ~ fill ~ [ #1 ] } } +\cs_new_eq:NN \__color_backend_fill_cmyk:n \__color_backend_fill:n +\cs_new_eq:NN \__color_backend_fill_gray:n \__color_backend_fill:n +\cs_new_eq:NN \__color_backend_fill_rgb:n \__color_backend_fill:n +\cs_new_protected:Npn \__color_backend_stroke:n #1 + { \__kernel_backend_literal:n { pdf : bc ~ stroke ~ [ #1 ] } } +\cs_new_eq:NN \__color_backend_stroke_cmyk:n \__color_backend_stroke:n +\cs_new_eq:NN \__color_backend_stroke_gray:n \__color_backend_stroke:n +\cs_new_eq:NN \__color_backend_stroke_rgb:n \__color_backend_stroke:n +\cs_new_protected:Npn \__color_backend_fill_separation:nn #1#2 + { + \__kernel_backend_literal:e + { pdf : bc ~ fill ~ \pdf_object_ref:n {#1} ~ [ #2 ] } + } +\cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2 + { + \__kernel_backend_literal:e + { pdf : bc ~ stroke ~ \pdf_object_ref:n {#1} ~ [ #2 ] } + } +\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn +\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn +\cs_new_eq:NN \__color_backend_fill_reset: \__color_backend_reset: +\cs_new_eq:NN \__color_backend_stroke_reset: \__color_backend_reset: +%% File: l3backend-box.dtx +\cs_new_protected:Npn \__box_backend_clip:N #1 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal_pdf:e + { + 0~ + \dim_to_decimal_in_bp:n { -\box_dp:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~ + re~W~n + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + \skip_horizontal:n { \box_wd:N #1 } + } +\cs_new_protected:Npn \__box_backend_rotate:Nn #1#2 + { \exp_args:NNf \__box_backend_rotate_aux:Nn #1 { \fp_eval:n {#2} } } +\cs_new_protected:Npn \__box_backend_rotate_aux:Nn #1#2 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal:e + { + x:rotate~ + \fp_compare:nNnTF {#2} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( #2 , 5 ) } } + } + \box_use:N #1 + \__kernel_backend_scope_end: + } +\cs_new_protected:Npn \__box_backend_scale:Nnn #1#2#3 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal:e + { + x:scale~ + \fp_eval:n { round ( #2 , 5 ) } ~ + \fp_eval:n { round ( #3 , 5 ) } + } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_scope_end: + } +%% 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_protected:Npn \__draw_backend_begin: + { \__draw_backend_scope_begin: } +\cs_new_protected:Npn \__draw_backend_end: + { \__draw_backend_scope_end: } +\cs_new_eq:NN \__draw_backend_scope_begin: \__kernel_backend_scope_begin: +\cs_new_eq:NN \__draw_backend_scope_end: \__kernel_backend_scope_end: +\cs_new_protected:Npn \__draw_backend_moveto:nn #1#2 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ m } + } +\cs_new_protected:Npn \__draw_backend_lineto:nn #1#2 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ l } + } +\cs_new_protected:Npn \__draw_backend_curveto:nnnnnn #1#2#3#4#5#6 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~ + c + } + } +\cs_new_protected:Npn \__draw_backend_rectangle:nnnn #1#2#3#4 + { + \__draw_backend_literal:e + { + \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ + \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~ + re + } + } +\cs_new_protected:Npn \__draw_backend_evenodd_rule: + { \bool_gset_true:N \g__draw_draw_eor_bool } +\cs_new_protected:Npn \__draw_backend_nonzero_rule: + { \bool_gset_false:N \g__draw_draw_eor_bool } +\bool_new:N \g__draw_draw_eor_bool +\cs_new_protected:Npn \__draw_backend_closepath: + { \__draw_backend_literal:n { h } } +\cs_new_protected:Npn \__draw_backend_stroke: + { \__draw_backend_literal:n { S } } +\cs_new_protected:Npn \__draw_backend_closestroke: + { \__draw_backend_literal:n { s } } +\cs_new_protected:Npn \__draw_backend_fill: + { + \__draw_backend_literal:e + { f \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_fillstroke: + { + \__draw_backend_literal:e + { B \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_clip: + { + \__draw_backend_literal:e + { W \bool_if:NT \g__draw_draw_eor_bool * } + } +\cs_new_protected:Npn \__draw_backend_discardpath: + { \__draw_backend_literal:n { n } } +\cs_new_protected:Npn \__draw_backend_dash_pattern:nn #1#2 + { + \__draw_backend_literal:e + { + [ + \exp_args:Nf \use:n + { \clist_map_function:nN {#1} \__draw_backend_dash:n } + ] ~ + \dim_to_decimal_in_bp:n {#2} ~ d + } + } +\cs_new:Npn \__draw_backend_dash:n #1 + { ~ \dim_to_decimal_in_bp:n {#1} } +\cs_new_protected:Npn \__draw_backend_linewidth:n #1 + { + \__draw_backend_literal:e + { \dim_to_decimal_in_bp:n {#1} ~ w } + } +\cs_new_protected:Npn \__draw_backend_miterlimit:n #1 + { \__draw_backend_literal:e { #1 ~ M } } +\cs_new_protected:Npn \__draw_backend_cap_butt: + { \__draw_backend_literal:n { 0 ~ J } } +\cs_new_protected:Npn \__draw_backend_cap_round: + { \__draw_backend_literal:n { 1 ~ J } } +\cs_new_protected:Npn \__draw_backend_cap_rectangle: + { \__draw_backend_literal:n { 2 ~ J } } +\cs_new_protected:Npn \__draw_backend_join_miter: + { \__draw_backend_literal:n { 0 ~ j } } +\cs_new_protected:Npn \__draw_backend_join_round: + { \__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 + { + \__draw_backend_cm_decompose:nnnnN {#1} {#2} {#3} {#4} + \__draw_backend_cm_aux:nnnn + } +\cs_new_protected:Npn \__draw_backend_cm_aux:nnnn #1#2#3#4 + { + \__kernel_backend_literal:e + { + x:rotate~ + \fp_compare:nNnTF {#1} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( -#1 , 5 ) } } + } + \__kernel_backend_literal:e + { + x:scale~ + \fp_eval:n { round ( #2 , 5 ) } ~ + \fp_eval:n { round ( #3 , 5 ) } + } + \__kernel_backend_literal:e + { + x:rotate~ + \fp_compare:nNnTF {#4} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( -#4 , 5 ) } } + } + } +\cs_new_protected:Npn \__draw_backend_cm_decompose:nnnnN #1#2#3#4#5 + { + \use:e + { + \__draw_backend_cm_decompose_auxi:nnnnN + { \fp_eval:n { (#1 + #4) / 2 } } + { \fp_eval:n { (#1 - #4) / 2 } } + { \fp_eval:n { (#3 + #2) / 2 } } + { \fp_eval:n { (#3 - #2) / 2 } } + } + #5 + } +\cs_new_protected:Npn \__draw_backend_cm_decompose_auxi:nnnnN #1#2#3#4#5 + { + \use:e + { + \__draw_backend_cm_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 ) } } + { \fp_eval:n { atand ( #4 , #1 ) } } + } + #5 + } +\cs_new_protected:Npn \__draw_backend_cm_decompose_auxii:nnnnN #1#2#3#4#5 + { + \use:e + { + \__draw_backend_cm_decompose_auxiii:nnnnN + { \fp_eval:n { ( #4 - #3 ) / 2 } } + { \fp_eval:n { ( #1 + #2 ) / 2 } } + { \fp_eval:n { ( #1 - #2 ) / 2 } } + { \fp_eval:n { ( #4 + #3 ) / 2 } } + } + #5 + } +\cs_new_protected:Npn \__draw_backend_cm_decompose_auxiii:nnnnN #1#2#3#4#5 + { + \fp_compare:nNnTF { abs( #2 ) } > { abs ( #3 ) } + { #5 {#1} {#2} {#3} {#4} } + { #5 {#1} {#3} {#2} {#4} } + } +\cs_new_protected:Npn \__draw_backend_box_use:Nnnnn #1#2#3#4#5 + { + \__kernel_backend_scope_begin: + \__kernel_backend_literal:n + { pdf:btrans~matrix~ #2 ~ #3 ~ #4 ~ #5 ~ 0 ~ 0 } + \hbox_overlap_right:n { \box_use:N #1 } + \__kernel_backend_literal:n { pdf:etrans } + \__kernel_backend_scope_end: + } +%% File: l3backend-graphics.dtx +\cs_new_protected:Npn \__graphics_backend_loaded:n #1 + { + \cs_if_exist:NTF \hook_gput_code:nnn + { + \hook_gput_code:nnn + { package / l3graphics / after } + { backend } + {#1} + } + {#1} + } +\__graphics_backend_loaded:n + { + \seq_set_from_clist:Nn \l_graphics_search_ext_seq + { .pdf , .eps , .ps , .png , .jpg , .jpeg , .bmp } + } +\__graphics_backend_loaded:n + { + \cs_new_eq:NN \__graphics_backend_getbb_eps:n \__graphics_read_bb:n + \cs_new_eq:NN \__graphics_backend_getbb_ps:n \__graphics_read_bb:n + } +\int_new:N \g__graphics_track_int +\cs_new_protected:Npn \__graphics_backend_include_eps:n #1 + { + \__kernel_backend_literal:e + { + PSfile = #1 \c_space_tl + llx = \dim_to_decimal_in_bp:n \l__graphics_llx_dim \c_space_tl + lly = \dim_to_decimal_in_bp:n \l__graphics_lly_dim \c_space_tl + urx = \dim_to_decimal_in_bp:n \l__graphics_urx_dim \c_space_tl + ury = \dim_to_decimal_in_bp:n \l__graphics_ury_dim + } + } +\cs_new_eq:NN \__graphics_backend_include_ps:n \__graphics_backend_include_eps:n +\cs_new_protected:Npn \__graphics_backend_include_jpg:n #1 + { \__graphics_backend_include_auxi:nn {#1} { image } } +\cs_new_eq:NN \__graphics_backend_include_jpeg:n \__graphics_backend_include_jpg:n +\cs_new_eq:NN \__graphics_backend_include_png:n \__graphics_backend_include_jpg:n +\cs_new_eq:NN \__graphics_backend_include_bmp:n \__graphics_backend_include_jpg:n +\cs_new_protected:Npn \__graphics_backend_include_auxi:nn #1#2 + { + \__graphics_backend_include_auxii:enn + { + \tl_if_empty:NF \l__graphics_pagebox_tl + { : \l__graphics_pagebox_tl } + \int_compare:nNnT \l__graphics_page_int > 1 + { :P \int_use:N \l__graphics_page_int } + \tl_if_empty:NF \l__graphics_decodearray_str + { :D \l__graphics_decodearray_str } + \bool_if:NT \l__graphics_interpolate_bool + { :I } + } + {#1} {#2} + } +\cs_new_protected:Npn \__graphics_backend_include_auxii:nnn #1#2#3 + { + \int_if_exist:cTF { c__graphics_ #2#1 _int } + { + \__kernel_backend_literal:e + { pdf:usexobj~@graphic \int_use:c { c__graphics_ #2#1 _int } } + } + { \__graphics_backend_include_auxiii:nnn {#2} {#1} {#3} } + } +\cs_generate_variant:Nn \__graphics_backend_include_auxii:nnn { e } +\cs_new_protected:Npn \__graphics_backend_include_auxiii:nnn #1#2#3 + { + \int_gincr:N \g__graphics_track_int + \int_const:cn { c__graphics_ #1#2 _int } { \g__graphics_track_int } + \__kernel_backend_literal:e + { + pdf:#3~ + @graphic \int_use:c { c__graphics_ #1#2 _int } ~ + \int_compare:nNnT \l__graphics_page_int > 1 + { page ~ \int_use:N \l__graphics_page_int \c_space_tl } + \tl_if_empty:NF \l__graphics_pagebox_tl + { + pagebox ~ \l__graphics_pagebox_tl \c_space_tl + bbox ~ + \dim_to_decimal_in_bp:n \l__graphics_llx_dim \c_space_tl + \dim_to_decimal_in_bp:n \l__graphics_lly_dim \c_space_tl + \dim_to_decimal_in_bp:n \l__graphics_urx_dim \c_space_tl + \dim_to_decimal_in_bp:n \l__graphics_ury_dim \c_space_tl + } + (#1) + \bool_lazy_or:nnT + { \l__graphics_interpolate_bool } + { ! \tl_if_empty_p:N \l__graphics_decodearray_str } + { + << + \tl_if_empty:NF \l__graphics_decodearray_str + { /Decode~[ \l__graphics_decodearray_str ] } + \bool_if:NT \l__graphics_interpolate_bool + { /Interpolate~true } + >> + } + } + } +\cs_new_protected:Npn \__graphics_backend_getbb_jpg:n #1 + { + \int_zero:N \l__graphics_page_int + \tl_clear:N \l__graphics_pagebox_tl + \__graphics_backend_getbb_auxi:nN {#1} \tex_XeTeXpicfile:D + } +\cs_new_eq:NN \__graphics_backend_getbb_jpeg:n \__graphics_backend_getbb_jpg:n +\cs_new_eq:NN \__graphics_backend_getbb_png:n \__graphics_backend_getbb_jpg:n +\cs_new_eq:NN \__graphics_backend_getbb_bmp:n \__graphics_backend_getbb_jpg:n +\cs_new_protected:Npn \__graphics_backend_getbb_pdf:n #1 + { + \tl_clear:N \l__graphics_decodearray_str + \bool_set_false:N \l__graphics_interpolate_bool + \__graphics_backend_getbb_auxi:nN {#1} \tex_XeTeXpdffile:D + } +\cs_new_protected:Npn \__graphics_backend_getbb_auxi:nN #1#2 + { + \int_compare:nNnTF \l__graphics_page_int > 1 + { \__graphics_backend_getbb_auxii:VnN \l__graphics_page_int {#1} #2 } + { \__graphics_backend_getbb_auxiii:nNnn {#1} #2 { :P 1 } { page 1 } } + } +\cs_new_protected:Npn \__graphics_backend_getbb_auxii:nnN #1#2#3 + { \__graphics_backend_getbb_auxiii:nNnn {#2} #3 { :P #1 } { page #1 } } +\cs_generate_variant:Nn \__graphics_backend_getbb_auxii:nnN { V } +\cs_new_protected:Npn \__graphics_backend_getbb_auxiii:nNnn #1#2#3#4 + { + \tl_if_empty:NTF \l__graphics_pagebox_tl + { \__graphics_backend_getbb_auxiv:VnNnn \l__graphics_pagebox_tl } + { \__graphics_backend_getbb_auxv:nNnn } + {#1} #2 {#3} {#4} + } +\cs_new_protected:Npn \__graphics_backend_getbb_auxiv:nnNnn #1#2#3#4#5 + { + \use:e + { + \__graphics_backend_getbb_auxv:nNnn {#2} #3 { : #1 #4 } + { + #5 + \tl_if_blank:nF {#1} + { \c_space_tl \__graphics_backend_getbb_pagebox:w #1 } + } + } + } +\cs_generate_variant:Nn \__graphics_backend_getbb_auxiv:nnNnn { V } +\cs_new_protected:Npn \__graphics_backend_getbb_auxv:nNnn #1#2#3#4 + { + \__graphics_bb_restore:nF {#1#3} + { \__graphics_backend_getbb_auxvi:nNnn {#1} #2 {#3} {#4} } + } +\cs_new_protected:Npn \__graphics_backend_getbb_auxvi:nNnn #1#2#3#4 + { + \hbox_set:Nn \l__graphics_internal_box { #2 #1 ~ #4 } + \dim_set:Nn \l__graphics_urx_dim { \box_wd:N \l__graphics_internal_box } + \dim_set:Nn \l__graphics_ury_dim { \box_ht:N \l__graphics_internal_box } + \__graphics_bb_save:n {#1#3} + } +\cs_new:Npn \__graphics_backend_getbb_pagebox:w #1 box {#1} +\cs_new_protected:Npn \__graphics_backend_include_pdf:n #1 + { + \tex_XeTeXpdffile:D #1 ~ + \int_compare:nNnT \l__graphics_page_int > 0 + { page ~ \int_use:N \l__graphics_page_int \c_space_tl } + \exp_after:wN \__graphics_backend_getbb_pagebox:w \l__graphics_pagebox_tl + } +\cs_new_protected:Npn \__graphics_backend_get_pagecount:n #1 + { + \int_const:cn { c__graphics_ #1 _pages_int } + { + \int_max:nn + { \int_use:N \tex_XeTeXpdfpagecount:D #1 ~ } + { 1 } + } + } +%% 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 } +\cs_new_protected:Npn \__pdf_backend_catalog_gput:nn #1#2 + { \__pdf_backend:n { put ~ @catalog << /#1 ~ #2 >> } } +\cs_new_protected:Npn \__pdf_backend_info_gput:nn #1#2 + { \__pdf_backend:n { docinfo << /#1 ~ #2 >> } } +\prop_new:N \g__pdf_backend_object_prop +\cs_new_protected:Npn \__pdf_backend_object_new: + { \int_gincr:N \g__pdf_backend_object_int } +\cs_new:Npn \__pdf_backend_object_ref:n #1 { @pdf.obj #1 } +\cs_new_eq:NN \__pdf_backend_object_id:n \__pdf_backend_object_ref:n +\cs_new_protected:Npn \__pdf_backend_object_write:nnn #1#2#3 + { + \use:c { __pdf_backend_object_write_ #2 :nn } + { \__pdf_backend_object_ref:n {#1} } {#3} + } +\cs_generate_variant:Nn \__pdf_backend_object_write:nnn { nne } +\cs_new_protected:Npn \__pdf_backend_object_write_array:nn #1#2 + { + \__pdf_backend:e + { obj ~ #1 ~ [ ~ \exp_not:n {#2} ~ ] } + } +\cs_new_protected:Npn \__pdf_backend_object_write_dict:nn #1#2 + { + \__pdf_backend:e + { obj ~ #1 ~ << ~ \exp_not:n {#2} ~ >> } + } +\cs_new_protected:Npn \__pdf_backend_object_write_fstream:nn #1#2 + { \__pdf_backend_object_write_stream:nnnn { f } {#1} #2 } +\cs_new_protected:Npn \__pdf_backend_object_write_stream:nn #1#2 + { \__pdf_backend_object_write_stream:nnnn { } {#1} #2 } +\cs_new_protected:Npn \__pdf_backend_object_write_stream:nnnn #1#2#3#4 + { + \__pdf_backend:e + { + #1 stream ~ #2 ~ + ( \exp_not:n {#4} ) ~ << \exp_not:n {#3} >> + } + } +\cs_new_protected:Npn \__pdf_backend_object_now:nn #1#2 + { + \int_gincr:N \g__pdf_backend_object_int + \exp_args:Nne \use:c { __pdf_backend_object_write_ #1 :nn } + { @pdf.obj \int_use:N \g__pdf_backend_object_int } + {#2} + } +\cs_generate_variant:Nn \__pdf_backend_object_now:nn { ne } +\cs_new:Npn \__pdf_backend_object_last: + { @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 + { + dest ~ ( \exp_not:n {#1} ) + [ + @thispage + \str_case:nnF {#2} + { + { xyz } { /XYZ ~ @xpos ~ @ypos ~ null } + { fit } { /Fit } + { fitb } { /FitB } + { fitbh } { /FitBH } + { fitbv } { /FitBV ~ @xpos } + { fith } { /FitH ~ @ypos } + { fitv } { /FitV ~ @xpos } + { fitr } { /Fit } + } + { /XYZ ~ @xpos ~ @ypos ~ \fp_eval:n { (#2) / 100 } } + ] + } + } +\cs_new_protected:Npn \__pdf_backend_destination:nnnn #1#2#3#4 + { + \exp_args:Ne \__pdf_backend_destination_aux:nnnn + { \dim_eval:n {#2} } {#1} {#3} {#4} + } +\cs_new_protected:Npn \__pdf_backend_destination_aux:nnnn #1#2#3#4 + { + \vbox_to_zero:n + { + \__kernel_kern:n {#4} + \hbox:n + { + \__pdf_backend:n { obj ~ @pdf_ #2 _llx ~ @xpos } + \__pdf_backend:n { obj ~ @pdf_ #2 _lly ~ @ypos } + } + \tex_vss:D + } + \__kernel_kern:n {#1} + \vbox_to_zero:n + { + \__kernel_kern:n { -#3 } + \hbox:n + { + \__pdf_backend:n + { + dest ~ (#2) + [ + @thispage + /FitR ~ + @pdf_ #2 _llx ~ @pdf_ #2 _lly ~ + @xpos ~ @ypos + ] + } + } + \tex_vss:D + } + \__kernel_kern:n { -#1 } + } +\cs_new_protected:Npn \__pdf_backend_compresslevel:n #1 + { \__kernel_backend_literal:e { dvipdfmx:config~z~ \int_eval:n {#1} } } +\cs_new_protected:Npn \__pdf_backend_compress_objects:n #1 + { + \bool_if:nF {#1} + { \__kernel_backend_literal:n { dvipdfmx:config~C~0x40 } } + } +\cs_new_protected:Npn \__pdf_backend_version_major_gset:n #1 + { + \cs_gset:Npe \__pdf_backend_version_major: { \int_eval:n {#1} } + \__kernel_backend_literal:e { pdf:majorversion~ \__pdf_backend_version_major: } + } +\cs_new_protected:Npn \__pdf_backend_version_minor_gset:n #1 + { + \cs_gset:Npe \__pdf_backend_version_minor: { \int_eval:n {#1} } + \__kernel_backend_literal:e { pdf:minorversion~ \__pdf_backend_version_minor: } + } +\cs_new:Npn \__pdf_backend_version_major: { 1 } +\cs_new:Npn \__pdf_backend_version_minor: { 5 } +\cs_new_protected:Npn \__pdf_backend_bdc:nn #1#2 + { \__kernel_backend_literal_page:n { /#1 ~ #2 ~ BDC } } +\cs_new_protected:Npn \__pdf_backend_emc: + { \__kernel_backend_literal_page:n { EMC } } +\cs_new_protected:Npn \__pdf_backend_pagesize_gset:nn #1#2 + { + \dim_gset:Nn \tex_pagewidth:D {#1} + \dim_gset:Nn \tex_pageheight:D {#2} + } +%% File: l3backend-opacity.dtx +\bool_lazy_and:nnT + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity 1 } { << /ca ~ 1 /CA ~ 1 >> } + } +\tl_new:N \l__opacity_backend_fill_tl +\tl_new:N \l__opacity_backend_stroke_tl +\tl_set:Nn \l__opacity_backend_fill_tl { 1 } +\tl_set:Nn \l__opacity_backend_stroke_tl { 1 } +\cs_new_protected:Npn \__opacity_backend_select:n #1 + { + \tl_set:Nn \l__opacity_backend_fill_tl {#1} + \tl_set:Nn \l__opacity_backend_stroke_tl {#1} + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity #1 } + { << /ca ~ #1 /CA ~ #1 >> } + \__kernel_backend_literal_pdf:n + { /opacity #1 ~ gs } + \group_insert_after:N \__opacity_backend_reset: + } +\cs_new_protected:Npn \__opacity_backend_reset: + { + \__kernel_backend_literal_pdf:n + { /opacity1 ~ gs } + } +\cs_new_protected:Npn \__opacity_backend_fill:n #1 + { + \exp_args:Nno \__opacity_backend_fill_stroke:nn + { #1 } + { \l__opacity_backend_stroke_tl } + } +\cs_new_protected:Npn \__opacity_backend_stroke:n #1 + { + \exp_args:No \__opacity_backend_fill_stroke:nn + { \l__opacity_backend_fill_tl } + { #1 } + } +\cs_new_protected:Npn \__opacity_backend_fill_stroke:nn #1#2 + { + \str_if_eq:nnTF {#1} {#2} + { \__opacity_backend_select:n {#1} } + { + \tl_set:Nn \l__opacity_backend_fill_tl {#1} + \tl_set:Nn \l__opacity_backend_stroke_tl {#2} + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity.fill #1 } + { << /ca ~ #1 >> } + \pdfmanagement_add:nnn { Page / Resources / ExtGState } + { opacity.stroke #2 } + { << /CA ~ #2 >> } + \__kernel_backend_literal_pdf:n + { /opacity.fill #1 ~ gs /opacity.stroke #2 ~ gs } + \group_insert_after:N \__opacity_backend_reset: + } + } +\bool_lazy_and:nnF + { \cs_if_exist_p:N \pdfmanagement_if_active_p: } + { \pdfmanagement_if_active_p: } + { + \cs_gset_protected:Npn \__opacity_backend_select:n #1 { } + \cs_gset_protected:Npn \__opacity_backend_fill_stroke:nn #1#2 { } + } +%% +%% +%% End of file `l3backend-xetex.def'. diff --git a/Master/tlpkg/tlpsrc/l3backend-dev.tlpsrc b/Master/tlpkg/tlpsrc/l3backend-dev.tlpsrc new file mode 100644 index 00000000000..cc23539bf28 --- /dev/null +++ b/Master/tlpkg/tlpsrc/l3backend-dev.tlpsrc @@ -0,0 +1,3 @@ +runpattern d texmf-dist/tex/latex-dev/l3backend +srcpattern d texmf-dist/source/latex-dev/l3backend +docpattern d texmf-dist/doc/latex-dev/l3backend -- cgit v1.2.3