From d4c8e8422877bdbec62dbaff2491b492b57281bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20B?= <2589111+jfbu@users.noreply.github.com> Date: Mon, 4 Jul 2022 18:32:08 +0200 Subject: [PATCH] Fix #10638: LaTeX code-blocks when highlighted token uses \fcolorbox This commit also does some internal refactoring in order to ease up projected PRs. --- sphinx/texinputs/sphinxlatexliterals.sty | 152 ++++++++++++----------- 1 file changed, 78 insertions(+), 74 deletions(-) diff --git a/sphinx/texinputs/sphinxlatexliterals.sty b/sphinx/texinputs/sphinxlatexliterals.sty index aa907333fab..6c7ecc6f6ba 100644 --- a/sphinx/texinputs/sphinxlatexliterals.sty +++ b/sphinx/texinputs/sphinxlatexliterals.sty @@ -111,83 +111,87 @@ \let\spx@original@set@color\set@color % About the produced output: % - it obeys current indentation, -% - frame of width \fboxrule is \fboxsep-separated from the contents, -% - the contents use the full available text width, -% - #1 = color of frame, #2 = color of background, -% - #3 = will be typeset above frame, in a non detachable way, -% - #4 = will be typeset below frame, in a non detachable way, -% - #5 = will be typeset within frame, -% #3 and #4 are expected to be already typeset \hbox'es. -% #5 are the contents, and in the context of usage of fancyvrb+framed by -% Sphinx, it will arrive here already transformed into horizontal boxes, -% as well as some interline penalties and glues. -\long\def\spx@fcolorbox #1#2#3#4#5{% +% - frame of width \sphinxverbatimborder is \sphinxverbatimsep -arated +% from the contents, +% - the contents use the full available text width, limited by indentation, +% - #1 = will be typeset above frame, in a non detachable way, +% - #2 = will be typeset below frame, in a non detachable way, +% - #3 = will be typeset within the frame. +% #1 and #2 are expected to be already typeset \hbox'es. +% #3 are the contents, and in the context of usage of fancyvrb+framed, +% it will arrive here already transformed into horizontal boxes, +% interline penalties and glues. +\long\def\spx@verb@FrameCommand #1#2#3{% + % These \hskips are for fancyvrb.sty measuring and will make the + % framing "adapt" to an indented context. + \ifspx@opt@verbatimwithframe\else\sphinxverbatimborder\z@\fi \hskip\@totalleftmargin - \hskip-\fboxsep\hskip-\fboxrule - % MEMO: this code is modified from color.sty's \color@b@x which has some - % features making it problematic when #5, as will be here the case in the - % context of usage of fancyvrb+framed+\spx@verb@@PreProcessLine may contain - % an unbalanced "color push". We must avoid an extra "color pop" located at - % a page break location. For this reason we do not add a \set@color or - % \normalcolor at start of #5. - \setbox\z@\hbox{\kern\fboxsep{#5}\kern\fboxsep}% - \dimen@\ht\z@ \advance\dimen@\fboxsep \ht\z@\dimen@ - \dimen@\dp\z@ \advance\dimen@\fboxsep \dp\z@\dimen@ - % \spx@CustomFbox uses already scope-limiting group, no need for one more - \spx@CustomFBox{#1}% frame color - {#3}% above frame, already a box - {#4}% below frame, already a box - {\def\set@color{\let\set@color\spx@original@set@color}% - \color{#2}% above trick avoids a color pop *after* \box\z@ - % MEMO: it is very very improbable that \color/\color@block - % will ever change (even if we raised some ticket at - % their issue tracker), but if they do, perhaps a - % change here could be needed in some distant future. - % MEMO: the \color@block "push + pop" happens *before* \box\z@ - \color@block{\wd\z@}{\ht\z@}{\dp\z@}% - \box\z@}% - \hskip-\fboxsep\hskip-\fboxrule + \hskip-\sphinxverbatimsep\hskip-\sphinxverbatimborder + \spx@verb@fcolorbox {#1}{#2}{#3}% + \hskip-\sphinxverbatimsep\hskip-\sphinxverbatimborder \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth }% -% #1 = color of frame -% #2 = for material above frame, such as a caption or a "continued" hint -% #3 = for material below frame, such as a caption or "continues on next page" -% #4 = contents; or rather if called from \spx@fcolorbox (only supported use -% case here), the contents are in \box\z@ and #4 are the instructions to -% "fill background color then draw contents \box\z@" -\long\def\spx@CustomFBox#1#2#3#4{% - \begingroup - % formerly, we used \@tempboxa, but let's use private box for maximal safety - \setbox\spx@verb@tempboxa\hbox{#4}% no (more) need for extra grouping (now) - \vbox{#2% above frame +\long\def\spx@verb@fcolorbox #1#2#3{% + % MEMO: in the context of framed.sty this will always expand inside some + % \hbox isolated from other code, so we can use \box\z@, \box\tw@,... + % with no need of extra group. +% + % MEMO: this code was originally using \color@b@x but the latter has + % problematic features regarding color in a context like here where #3 + % may contain an unbalanced "color push". +% + % MEMO: Some PDF viewers have (or had) issues when the external frame is + % drawn first, then the background color is added. So we will draw first + % the background color (and let it extend to the frame area) then, hence + % on top of it the frame. And we draw the contents latest. +% + % TODO: add top right bottom left padding possibilities. + % Prepare a box with the contents and reserved space for framing. + \setbox\z@\hbox{\kern\dimexpr\sphinxverbatimborder+\sphinxverbatimsep\relax + {#3}\kern\dimexpr\sphinxverbatimborder+\sphinxverbatimsep\relax}% + \ht\z@ \dimexpr\ht\z@+\sphinxverbatimsep+\sphinxverbatimborder\relax + \dp\z@ \dimexpr\dp\z@+\sphinxverbatimsep+\sphinxverbatimborder\relax + % Prepare colored background + \setbox\tw@\hbox{{\color{VerbatimColor}\vrule\@width\wd\z@\@height\ht\z@\@depth\dp\z@}}% + \vbox{#1% continuation hint attached above frame % draw frame border _latest_ to avoid pdf viewer issue % be careful not to cause "color push + contents + color pop" - \kern\fboxrule - \hbox{\kern\fboxrule - \copy\spx@verb@tempboxa% \copy to keep \wd, \dp, \ht for later - {\color{#1}% frame color - \kern-\wd\spx@verb@tempboxa\kern-\fboxrule - \vrule\@width\fboxrule - \kern\wd\spx@verb@tempboxa - \vrule\@width\fboxrule}% - }% - {\color{#1}% frame color - \kern-\dimexpr\ht\spx@verb@tempboxa+\dp\spx@verb@tempboxa+\fboxrule\relax - \hrule\@height\fboxrule - \kern\dimexpr\ht\spx@verb@tempboxa+\dp\spx@verb@tempboxa\relax - \hrule\@height\fboxrule}% - #3% below frame - }% - \endgroup + % there will be a small "\lineskip" space here from TeX + % the colored background + \copy\tw@ + % stroke the frame + \kern-\dimexpr\ht\tw@+\dp\tw@\relax + {\color{VerbatimBorderColor}% frame color + \hrule\@height\sphinxverbatimborder % width computed by TeX + \setbox\tw@\hb@xt@\wd\z@ + {% the vrule height will be auto computed later by TeX + \vrule\@width\sphinxverbatimborder + \hss + \vrule\@width\sphinxverbatimborder + }% + \ht\tw@\dimexpr\ht\z@-\sphinxverbatimborder\relax + \dp\tw@\dimexpr\dp\z@-\sphinxverbatimborder\relax + \box\tw@ + \hrule\@height\sphinxverbatimborder + }% color pop here + % now the contents + \kern-\dimexpr\ht\tw@+\dp\tw@\relax + \box\z@ + % Former code had a \hrule here so we need to suppress interline glue + % to keep exact same output now that it is a \hbox above + \nointerlineskip + % TODO: add some \lineskip glue here, this is all in a \vbox so can't split + #2% continuation hint attached below frame + }% end of \vbox }% \def\spx@fcolorbox@put@c#1{% hide width from framed.sty measuring - \moveright\dimexpr\fboxrule+.5\wd\spx@verb@tempboxa\hb@xt@\z@{\hss#1\hss}% + \moveright.5\wd\tw@\hb@xt@\z@{\hss#1\hss}% }% \def\spx@fcolorbox@put@r#1{% right align with contents, width hidden - \moveright\dimexpr\fboxrule+\wd\spx@verb@tempboxa-\fboxsep\hb@xt@\z@{\hss#1}% + \moveright\dimexpr\wd\tw@-\sphinxverbatimsep-\sphinxverbatimborder\hb@xt@\z@{\hss#1}% }% \def\spx@fcolorbox@put@l#1{% left align with contents, width hidden - \moveright\dimexpr\fboxrule+\fboxsep\hb@xt@\z@{#1\hss}% + \moveright\dimexpr\sphinxverbatimborder+\sphinxverbatimsep\hb@xt@\z@{#1\hss}% }% % \def\sphinxVerbatim@Continued @@ -204,15 +208,14 @@ \newcommand*\literalblockcontinuedname{continued from previous page}% \newcommand*\literalblockcontinuesname{continues on next page}% % -\def\spx@verbatimfcolorbox{\spx@fcolorbox{VerbatimBorderColor}{VerbatimColor}}% \def\sphinxVerbatim@FrameCommand - {\spx@verbatimfcolorbox\sphinxVerbatim@Before\sphinxVerbatim@After}% + {\spx@verb@FrameCommand\sphinxVerbatim@Before\sphinxVerbatim@After}% \def\sphinxVerbatim@FirstFrameCommand - {\spx@verbatimfcolorbox\sphinxVerbatim@Before\sphinxVerbatim@Continues}% + {\spx@verb@FrameCommand\sphinxVerbatim@Before\sphinxVerbatim@Continues}% \def\sphinxVerbatim@MidFrameCommand - {\spx@verbatimfcolorbox\sphinxVerbatim@Continued\sphinxVerbatim@Continues}% + {\spx@verb@FrameCommand\sphinxVerbatim@Continued\sphinxVerbatim@Continues}% \def\sphinxVerbatim@LastFrameCommand - {\spx@verbatimfcolorbox\sphinxVerbatim@Continued\sphinxVerbatim@After}% + {\spx@verb@FrameCommand\sphinxVerbatim@Continued\sphinxVerbatim@After}% % For linebreaks inside Verbatim environment from package fancyvrb. \newbox\sphinxcontinuationbox @@ -675,8 +678,6 @@ \fi \global\let\sphinxLiteralBlockLabel\empty \global\let\sphinxVerbatimTitle\empty - \fboxsep\sphinxverbatimsep \fboxrule\sphinxverbatimborder - \ifspx@opt@verbatimwithframe\else\fboxrule\z@\fi \let\FrameCommand \sphinxVerbatim@FrameCommand \let\FirstFrameCommand\sphinxVerbatim@FirstFrameCommand \let\MidFrameCommand \sphinxVerbatim@MidFrameCommand @@ -756,8 +757,11 @@ \dp\sphinxVerbatim@ContentsBox+ \ht\sphinxVerbatim@TitleBox+ \dp\sphinxVerbatim@TitleBox+ - 2\fboxsep+2\fboxrule+ + 2\sphinxverbatimsep+\ifspx@opt@verbatimwithframe 2\sphinxverbatimborder+\fi % try to account for external frame parameters + % MEMO: this is because the sphinxheavybox (for warning admonitions) + % environment sets \FrameSep and \FrameRule + % TODO: fix this bad implicit dependency \FrameSep+\FrameRule+ % Usage here of 2 baseline distances is empirical. % In border case where code-block fits barely in remaining space,