% \iffalse meta-comment % %% File: pdfmanagement-firstaid.dtx % % Copyright (C) 2018-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 % % http://www.latex-project.org/lppl.txt % % This file is part of the "LaTeX PDF management testphase 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/pdfresources % % for those people who are interested. % %<*driver> \DocumentMetadata{pdfstandard=A-2b} \documentclass[full]{l3doc} \usepackage{array,booktabs} \hypersetup{pdfauthor=The LaTeX Project,pdftitle=pdfmanagement-firstaid (LaTeX PDF management testphase bundle)} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % \title{^^A % The \pkg{pdfmanagement-firstaid} package -- temporary patches and package replacements ^^A % \\ \LaTeX{} PDF management testphase bundle % } % % \author{^^A % The \LaTeX{} Project\thanks % {^^A % E-mail: % \href{mailto:latex-team@latex-project.org} % {latex-team@latex-project.org}^^A % }^^A % } % % \date{Version 0.96f, released 2024-03-01} % % \maketitle % \begin{documentation} % % \section{\pkg{pdfmanagement-firstaid} documentation} % This code is temporary! It tries to patch commands of other packages or even % replace package which are incompatible with the pdfmanagement, % to remove clashes and test if everything works as expected. % This code should disappear when packages adapt to the central interfaces. % % The package contains an number of sections for various packages. Every % section can be disabled in (the first) \cs{DocumentMetadata} with % |debug={firstaidoff={name1,name2,...},...}|. % \begin{macrocode} %<*package> \ProvidesExplPackage{pdfmanagement-firstaid}{2024-03-01}{0.96f} {LaTeX PDF management testphase bundle / firstaid-patches} %<@@=pdfmanagement> \clist_map_inline:nn {pgf,transparent,xmp,pdflscape,xcolor,color, beamer,output,colorspace,fontspec,luacolor} { \bool_new:c { g_@@_firstaid_#1_bool } \bool_gset_true:c { g_@@_firstaid_#1_bool } } \clist_map_inline:Nn \g_@@_firstaidoff_clist { \bool_if_exist:cT { g_@@_firstaid_#1_bool } { \bool_gset_false:c { g_@@_firstaid_#1_bool } } } \msg_new:nnn { pdfmanagement } { firstaid } { loading~pdfmanagement~firstaid~code~for~#1 } \msg_new:nnn { pdfmanagement } { firstaid-changed } { package~#1~has~changed.~Check~if~patch~is~still~valid! } \msg_new:nnn { pdfmanagement } { firstaid-disabled } { The~loading~of~package~#1~is~disabled.\\ It~is~not~compatible~with~the~PDF~management. } \msg_new:nnn { pdfmanagement } { firstaid-too-old } { Package~#1~is~too~old~and~not~compatible.\\ Get~at~least~version~#2.} % \end{macrocode} % \subsection{Fontspec} % When using luaLaTeX opacity is broken (issue \#30) as % fontspec/luaotfload doesn't use the pdfmanagement but write to ExtGState directly % To repair this some new lua code is needed. It also needs a new fontspec % and a change in the color key. % \begin{macrocode} \sys_if_engine_luatex:T { \bool_if:NT \g_@@_firstaid_fontspec_bool { \AddToHook{package/fontspec/after} { \@ifpackagelater{fontspec}{2023-11-05} {\typeout{PDF~Management:~fontspec~firstaid~ignored}} { \def\c__fontspec_opacity_tl{} \__fontspec_keys_define_code:nnn {fontspec} {Color} { \color_if_exist:nTF {#1} { \tl_set:Nn \l__fontspec_hexcol_tl {#1} } { \cs_if_exist:cTF { \token_to_str:N \color@ #1 } { \convertcolorspec{named}{#1}{HTML}\l__fontspec_hexcol_tl } { \int_compare:nTF { \tl_count:n {#1} == 6 } { \tl_set:Nn \l__fontspec_hexcol_tl {#1} } { \int_compare:nTF { \tl_count:n {#1} == 8 } { \fontspec_parse_colour:viii #1 } { \bool_if:NF \l__fontspec_firsttime_bool { \__fontspec_warning:nx {bad-colour} {#1} } } } } } } % \end{macrocode} % add a comma % \begin{macrocode} \__fontspec_keys_define_code:nnn {fontspec} {Opacity} { \int_set:Nn \l__fontspec_tmp_int {255} \__fontspec_int_mult_truncate:Nn \l__fontspec_tmp_int { #1 } \tl_if_eq:NNF \l__fontspec_opacity_tl \c__fontspec_opacity_tl { \bool_if:NF \l__fontspec_firsttime_bool { \__fontspec_warning:nx {opa-twice} {#1} } } \tl_set:Nx \l__fontspec_opacity_tl { , \int_compare:nT { \l__fontspec_tmp_int <= "F } {0} % zero pad \int_to_hex:n { \l__fontspec_tmp_int } } } % \end{macrocode} % and a brace % \begin{macrocode} \cs_set:Nn \__fontspec_get_features:n { \__fontspec_init_fontface: \__fontspec_keys_set_known:nxN {fontspec-renderer} {\l__fontspec_fontfeat_clist,#1} \l__fontspec_keys_leftover_clist \__fontspec_keys_set_known:nxN {fontspec} {\l__fontspec_keys_leftover_clist} \l__fontspec_keys_leftover_clist \keys_set:nV {fontspec-opentype} \l__fontspec_keys_leftover_clist \tl_if_empty:NF \l__fontspec_mapping_tl { \__fontspec_update_featstr:n { mapping = \l__fontspec_mapping_tl } } \str_if_eq:eeF { \l__fontspec_hexcol_tl \l__fontspec_opacity_tl } { \c__fontspec_hexcol_tl \c__fontspec_opacity_tl } { \__fontspec_update_featstr:n { color = {\l__fontspec_hexcol_tl\l__fontspec_opacity_tl } } } } } } } } % \end{macrocode} % \subsection{\pkg{beamer}} % \pkg{beamer} made use of the now unsupported syntax |linkbordercolor={.5 .5 .5}|. % This has been changed so the patch has been removed. % % \subsection{\pkg{color}} % % \pkg{color} is not incompatible, but the new \pkg{hyperref} driver makes use of % \pkg{l3color} to set the colors. It is therefore necessary to patch some % internal \pkg{color} commands, so % that colors defined with its \cs{definecolor} command are known to \pkg{l3color} and % so \pkg{hyperref}. This only supports the color models from l3color (which covers % all standard model of the \pkg{color} package). The |named| model is mapped to % \cs{color_set:nn}. % % This patch serves also as test to check if this change can be safely % added to \pkg{color} later. % \begin{macrocode} \bool_if:NT \g_@@_firstaid_color_bool { \declare@file@substitution{color.sty}{color-ltx.sty} } % \end{macrocode} % % \subsection{\pkg{xcolor}} % % \pkg{xcolor} is not incompatible, but the new \pkg{hyperref} driver makes use of % \pkg{l3color} to set the colors. It is therefore necessary to patch \pkg{xcolor}, so % that colors defined with its \cs{definecolor} command are known to \pkg{l3color} and % so \pkg{hyperref}. This only supports the color model from l3color. Colors defined % with the models |cmy| and |tHsb| are silently ignored. % % The |named| model is mapped to \cs{color_set:nn}. % % \begin{macrocode} \bool_if:NT \g_@@_firstaid_xcolor_bool { \AddToHook { package/xcolor/after } {\RequirePackage{xcolor-patches-tmp-ltx}} % \end{macrocode} % The patch must before color definitions are loaded, which will happen in % hooks in a newer xcolor: % \begin{macrocode} \DeclareHookRule{package/xcolor/after}{pdfmanagement-firstaid}{before}{xcolor} } % \end{macrocode} % % \subsection{luacolor} % % The luacolor package doesn't take colors from l3color into account. % We add a fix, but only for pdf mode. luacolor can disable the % code by clearing the hook if needed. % % \begin{macrocode} \bool_lazy_all:nT { {\sys_if_engine_luatex_p:} {\g_@@_firstaid_luacolor_bool} {\sys_if_output_pdf_p:} } { \AddToHook{package/luacolor/after} { \cs_set_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} \LuaCol@setattribute\LuaCol@Attribute { \directlua { oberdiek.luacolor.get("\luaescapestring{#1~#2}") } } } \cs_set_protected:Npn \__color_backend_fill:n #1 { \tl_set:Nn \l__color_backend_fill_tl {#1} \LuaCol@setattribute\LuaCol@Attribute { \directlua { oberdiek.luacolor.get("\luaescapestring{#1}") } } } \cs_set_protected:Npn \__color_backend_stroke:n #1 { \tl_set:Nn \l__color_backend_stroke_tl {#1} \LuaCol@setattribute\LuaCol@Attribute { \directlua { oberdiek.luacolor.get("\luaescapestring{#1}") } } } \cs_set_protected:Npn \__color_backend_reset: {} \cs_set_eq:NN \__color_backend_fill_reset: \__color_backend_reset: \cs_set_eq:NN \__color_backend_stroke_reset: \__color_backend_reset: } } % \end{macrocode} % \subsection{\pkg{pgf}} % % In \pkg{pgf}, resource management is set up in the file |pgfutil-common.tex|. % This then provides three functions for adding to the resources, all of which % are objects: % \begin{itemize} % \item \cs{pgfutil@addpdfresource@extgs}: Extended graphics state % \item \cs{pgfutil@addpdfresource@colorspaces}: Color spaces % \item \cs{pgfutil@addpdfresource@patterns}: Patterns % \end{itemize} % % These resource dictionaries are used by adding entries in a cumulative sense; % the macro layer deals with ensuring that each entry is only given once. Note % that the objects themselves must be given only once for each page. % % To support these functions, there are a series of set-up macros which install % these resources. That has to take place for every page: the exact route % therefore depends on the driver. % % For the pdfmanagement project we need to avoid that pgf interferes in ExtGState, % ColorSpace and Pattern (Shadings are added to the xform resources and so probably % unproblematic for now). % The actual patch is in a file hook guarded by the boolean, % the rest of the code is always defined. % \begin{macrocode} \bool_if:NT \g_@@_firstaid_pgf_bool { \msg_info:nnn{pdfmanagement }{firstaid}{pgf} \AddToHook { file/pgfrcs.sty/after } { \cs_set_eq:NN \@@_pgfori_pgfutil@setuppdfresources \pgfutil@setuppdfresources \def\pgfutil@setuppdfresources { \pdfmanagement_if_active:TF { \@@_pgf_sys_setuppdfresources_plain: } { \@@_pgfori_pgfutil@setuppdfresources } } } } %\def\pgfutil@addpdfresource@extgs#1{\pgf@sys@addpdfresource@extgs@plain{#1}} %\def\pgfutil@addpdfresource@colorspaces#1{\pgf@sys@addpdfresource@colorspaces@plain{#1}} %\def\pgfutil@addpdfresource@patterns#1{\pgf@sys@addpdfresource@patterns@plain{#1}} %\def\pgfutil@setuppdfresources{\pgf@sys@setuppdfresources@plain} % \pgf@sys@pdf@possible@resources %used in xform %Trying to patch pgf .. \cs_new_protected:Npn \@@_pgf_sys_setuppdfresources_plain: { %objects are already created ... \def\pgf@sys@pdf@possible@resources { /ColorSpace~\pdf_object_ref:n {__pdf/Page/Resources/ColorSpace} /Pattern ~\pdf_object_ref:n {__pdf/Page/Resources/Pattern} /ExtGState ~\pdf_object_ref:n {__pdf/Page/Resources/ExtGState} } \let\pgf@sys@pdf@check@resources=\relax% %not sure if needed, but perhaps the lists are used somewhere else ... \let\pgf@sys@pgf@resource@list@extgs=\pgfutil@empty% \let\pgf@sys@pgf@resource@list@patterns=\pgfutil@empty% \let\pgf@sys@pgf@resource@list@colorspaces=\pgfutil@empty% % the commands to add page resources \def\pgf@sys@addpdfresource@extgs@plain##1 { %\exp_after:wN %for transparent which passes a command \@@_patch_pgfextgs:w ##1\q_stop } \def\pgf@sys@addpdfresource@patterns@plain##1 { \@@_patch_pgfpatterns:w ##1\q_stop } \def\pgf@sys@addpdfresource@colorspaces@plain##1 { \@@_patch_pgfcolorspaces:w ##1\q_stop } } %\AtEndPreamble{\pgfutil@setuppdfresources} % helper commands as pgf doesn't pass resources as two arguments % code to add to the resources existing stuff in the format "/name value": \cs_new:Npn \@@_split_dict_entry_aux:NNw #1 #2 /#3~#4\q_stop { \tl_set:Nn #1 {#3} \tl_set:Nn #2 {#4} } \cs_generate_variant:Nn \tl_trim_spaces:n{V} \cs_generate_variant:Nn \pdfmanagement_add:nnn {nee} \cs_new:Npn \@@_patch_pgfextgs:w #1/#2<<#3>>#4\q_stop { \tl_set:Ne\l_tmpa_tl{#2} \pdfmanagement_add:nee {Page/Resources/ExtGState}{\tl_trim_spaces:V\l_tmpa_tl}{<<#3 #4>>} } \cs_new:Npn \@@_patch_pgfpatterns:w #1/#2\space#3\q_stop { \pdfmanagement_add:nee {Page/Resources/Pattern}{\tl_trim_spaces:n{#2}}{#3} } \cs_new:Npn \@@_patch_pgfcolorspaces:w #1/#2[#3]#4\q_stop { \pdfmanagement_add:nee {Page/Resources/ColorSpace}{\tl_trim_spaces:n{#2}}{[#3]} } % \end{macrocode} % \subsection{\pkg{transparent}} % We check if the new version is used and issue a warning otherwise % \begin{macrocode} \bool_if:NT \g_@@_firstaid_transparent_bool { \AddToHook{package/transparent/after} { \@ifpackagelater{transparent}{2022-10-27}{} { \msg_warning:nnnn{pdfmanagement}{firstaid-too-old} {transparent} {1.5~from~2022-10-27} } } } % \end{macrocode} % \subsection{\pkg{pdflscape}} % We check if the new version is used and issue a warning otherwise % \begin{macrocode} \bool_if:NT \g_@@_firstaid_pdflscape_bool { \AddToHook{package/pdflscape/after} { \@ifpackagelater{pdflscape}{2022-10-27}{} { \msg_warning:nnnn{pdfmanagement}{firstaid-too-old} {pdflscape} {0.13~from~2022-10-27} } } } % \end{macrocode} % % \subsection{xmp} % This handles the new xmp code. % \begin{macrocode} \bool_if:NT \g_@@_firstaid_xmp_bool { \disable@package@load{hyperxmp}{\msg_warning:nnn{pdfmanagement}{firstaid-disabled}{hyperxmp}} \disable@package@load{pdfx} {\msg_warning:nnn{pdfmanagement}{firstaid-disabled}{pdfx}} \AddToHook{package/doclicense/after} { \AtBeginDocument { \hypersetup { pdfcopyright = {\doclicenseLongTextForHyperref}, pdflicenseurl = {\doclicenseURL}, } } } } % % \end{macrocode} % \subsection{\pkg{colorspace}} % This is rather difficult as no real places to inject patches % at first a try to avoid that its ExtGState is missing: % it can not be avoided to recreate the objects (and so to get duplicates) % as colorspace uses temporary macros whose contents is lost. % \begin{macrocode} %<*package> \bool_if:NT \g_@@_firstaid_colorspace_bool { \AddToHook { package/colorspace/after } {\RequirePackage{colorspace-patches-tmp-ltx}} } % % \end{macrocode}% % % \end{documentation} % \PrintIndex