diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:25:40 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:25:40 +0000 |
commit | cf7da1843c45a4c2df7a749f7886a2d2ba0ee92a (patch) | |
tree | 18dcde1a8d1f5570a77cd0c361de3b490d02c789 /sphinx/texinputs/sphinxpackageboxes.sty | |
parent | Initial commit. (diff) | |
download | sphinx-cf7da1843c45a4c2df7a749f7886a2d2ba0ee92a.tar.xz sphinx-cf7da1843c45a4c2df7a749f7886a2d2ba0ee92a.zip |
Adding upstream version 7.2.6.upstream/7.2.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sphinx/texinputs/sphinxpackageboxes.sty')
-rw-r--r-- | sphinx/texinputs/sphinxpackageboxes.sty | 854 |
1 files changed, 854 insertions, 0 deletions
diff --git a/sphinx/texinputs/sphinxpackageboxes.sty b/sphinx/texinputs/sphinxpackageboxes.sty new file mode 100644 index 0000000..b0d3707 --- /dev/null +++ b/sphinx/texinputs/sphinxpackageboxes.sty @@ -0,0 +1,854 @@ +%% COLOURED BOXES +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxpackageboxes}[2023/03/19 v6.2.0 advanced colored boxes] +% Optionally executes \RequirePackage for: +% +% - pict2e. Ideally we would like to use the v0.4a 2020/08/16 release of this +% package as it allows dimensional arguments to its \moveto, \lineto, etc... +% Or we could use extra package "picture". We opt for custom wrappers +% \spx@moveto, \spx@lineto, ..., working with old versions. +% +% - ellipse. This package extends pict2e with elliptical arcs. Its author +% Daan Leijen also has contributed package longfbox which is part of +% TeXLive. Had I known about it, I would perhaps have based Sphinx CSS on +% top of longfbox at least partly. But this would not have spared me all +% the work in sphinx.sty, which was a long walk until 6.2.0 version. +% Besides I don't need the breakable boxes from longfbox, as Sphinx has +% its own rather advanced layer on top of framed. I would need to check if +% some thorny color issues solved by Sphinx (and not by tcolorbox) at page +% breaks are solved by longfbox as well. (I have not tested) + +% At 6.2.0 refactoring, we do not wait for at begin document to try to load +% pict2e. Actually since 6.0.0 the default is for code-blocks to use +% rounded boxes, and the only reason since then to wait "at begin document" +% was to check if user had reverted that default and in fact pict2e was not +% needed. But with \sphinxbox, we can not know for sure even in that case +% that pict2e is not needed. And even back then it would have been possible +% to user to try to employ \sphinxsetup via raw directive in document body +% and require some rounded corners (which was thus impossible to satisfy). +% Time to be much simpler and attempt unconditionally to load pict2e +% immediately. This will also have advantage that we can use +% \@ifpackageloaded{pict2e} and not have to query and save its setting later +% at begin document. +\IfFileExists{pict2e.sty} + {\RequirePackage{pict2e}} + {\PackageWarningNoLine{sphinx}{% + The package pict2e is required for rounded boxes.\MessageBreak + It does not seem to be available on your system.\MessageBreak + Options for setting radii will be ignored% + }% + % Formerly a \sphinxbuildwarning was issued but if we did that now it + % would mean that the produced PDF will always have a red banner near its + % end about pict2e not being available if indeed it is not available, even + % if user has reverted the default and dropped rounded corners. Formerly + % the serious warning was done after having checked at begin document that + % indeed a rounded corner option had been used. As we drop the check now, + % let's be more discrete and simply duplicate the earlier warning to make + % it visible near end of compilation log and console output. + \AtEndDocument{\PackageWarningNoLine{sphinx}{% + The package pict2e is required for rounded boxes.\MessageBreak + As it does not seem to be available on your system,\MessageBreak + options setting radii have all been ignored}}% + }% + +\IfFileExists{ellipse.sty} + {\RequirePackage{ellipse}} + {\PackageWarningNoLine{sphinx}{% + The package ellipse is required for elliptical corners.\MessageBreak + It does not seem to be available on your system.\MessageBreak + All non-straight corners will use circle arcs.% + }% + \AtEndDocument{\PackageWarningNoLine{sphinx}{% + The package ellipse is required for elliptical corners.\MessageBreak + As it does not seem to be available on your system,\MessageBreak + all non-straight corners have used circle arcs.}}% + }% + +% The pict2e release v0.4b of 2020/09/30 does not allocate scratch dimen +% register \@tempdimd which ellipse package uses. Thus ellipse package is +% broken since (written on March 20, 2023). Simply allocate the register +% ourself to fix that, pending some upstream fix. +\@ifpackageloaded{ellipse}{\ifdefined\@tempdimd\else\newdimen\@tempdimd\fi}{} + +% Provides box registers \spx@tempboxa, \spx@tempboxb usable in other places +\newbox\spx@tempboxa +\newbox\spx@tempboxb + +%%%%%%%%%%%%%%%% +% Internal registers, conditionals, colors to be configured by each caller +% via a preliminary "setup" call +% +\newif\ifspx@boxes@withshadow +\newif\ifspx@boxes@insetshadow +\newif\ifspx@boxes@withbackgroundcolor +\newif\ifspx@boxes@withshadowcolor +\newif\ifspx@boxes@withbordercolor +\newif\ifspx@boxes@shadowinbbox +% +\newdimen\spx@boxes@border +\newdimen\spx@boxes@border@top +\newdimen\spx@boxes@border@right +\newdimen\spx@boxes@border@bottom +\newdimen\spx@boxes@border@left +% +\newdimen\spx@boxes@padding@top +\newdimen\spx@boxes@padding@right +\newdimen\spx@boxes@padding@bottom +\newdimen\spx@boxes@padding@left +% +\newdimen\spx@boxes@shadow@xoffset +\newdimen\spx@boxes@shadow@yoffset +% +\newdimen\spx@boxes@radius@topleft@x +\newdimen\spx@boxes@radius@topright@x +\newdimen\spx@boxes@radius@bottomright@x +\newdimen\spx@boxes@radius@bottomleft@x +\newdimen\spx@boxes@radius@topleft@y +\newdimen\spx@boxes@radius@topright@y +\newdimen\spx@boxes@radius@bottomright@y +\newdimen\spx@boxes@radius@bottomleft@y +% +% These colors will be set to colors defined appropriately by caller of +% \spx@boxes@fcolorbox@setup macro +% spx@boxes@bordercolor +% spx@boxes@backgroundcolor +% spx@boxes@shadowcolor +% spx@boxes@textcolor + +%%%%%%%%%%%%%%%% +% "setup" macro +% +% It must be called prior to \spx@boxes@fcolorbox for parameters of the latter +% to be initialized. +% +% It also prepares \spx@boxes@fcolorbox to expand to one of +% \spx@boxes@fcolorbox@rectangle or \spx@boxes@fcolorbox@rounded depending on +% the configuration and availability of the pict2e package. +% +% The #1 is one of: pre, topic, warning, danger, etc.... +% +% We delay until here the parsing of radii options to extract x and y +% components. +\def\spx@boxes@setradii#1 #2 #3\@nnil#4#5{% + #4\dimexpr#1\relax + #5\dimexpr#2\relax + \ifdim#5=-\maxdimen#5#4\fi + % if one of them is zero or negative set both to zero + \ifdim#4>\z@\else#4\z@#5\z@\fi + \ifdim#5>\z@\else#4\z@#5\z@\fi +}% +% if ellipse.sty is not available ignore the second component of all radii +% specifications, use circle arcs with radius the x component +\@ifpackageloaded{ellipse} + {} + {\def\spx@boxes@setradii#1 #2 #3\@nnil#4#5{#4\dimexpr#1\relax #5#4}} + +% Using \dimexpr for maximal user input flexibility. +\def\spx@boxes@fcolorbox@setup#1{% + \spx@boxes@border@top \dimexpr\@nameuse{spx@#1@border@top}\relax + \spx@boxes@border@right \dimexpr\@nameuse{spx@#1@border@right}\relax + \spx@boxes@border@bottom\dimexpr\@nameuse{spx@#1@border@bottom}\relax + \spx@boxes@border@left \dimexpr\@nameuse{spx@#1@border@left}\relax + \spx@boxes@border \dimexpr\@nameuse{spx@#1@border}\relax + % + \spx@boxes@padding@top \dimexpr\@nameuse{spx@#1@padding@top}\relax + \spx@boxes@padding@right \dimexpr\@nameuse{spx@#1@padding@right}\relax + \spx@boxes@padding@bottom\dimexpr\@nameuse{spx@#1@padding@bottom}\relax + \spx@boxes@padding@left \dimexpr\@nameuse{spx@#1@padding@left}\relax + % + \edef\spx@temp{\csname spx@#1@radius@topleft\endcsname\space}% + \expandafter + \spx@boxes@setradii + \spx@temp + {-\maxdimen} + \@nnil + \spx@boxes@radius@topleft@x\spx@boxes@radius@topleft@y + \edef\spx@temp{\csname spx@#1@radius@topright\endcsname\space}% + \expandafter + \spx@boxes@setradii + \spx@temp + {-\maxdimen} + \@nnil + \spx@boxes@radius@topright@x\spx@boxes@radius@topright@y + \edef\spx@temp{\csname spx@#1@radius@bottomright\endcsname\space}% + \expandafter + \spx@boxes@setradii + \spx@temp + {-\maxdimen} + \@nnil + \spx@boxes@radius@bottomright@x\spx@boxes@radius@bottomright@y + \edef\spx@temp{\csname spx@#1@radius@bottomleft\endcsname\space}% + \expandafter + \spx@boxes@setradii + \spx@temp + {-\maxdimen} + \@nnil + \spx@boxes@radius@bottomleft@x\spx@boxes@radius@bottomleft@y + % + \@nameuse{ifspx@#1@withshadow}% + \spx@boxes@withshadowtrue + \spx@boxes@shadow@xoffset \dimexpr\@nameuse{spx@#1@shadow@xoffset}\relax + \spx@boxes@shadow@yoffset \dimexpr\@nameuse{spx@#1@shadow@yoffset}\relax + \else + \spx@boxes@withshadowfalse + \fi + % not nesting in previous to avoid TeX conditional subtleties + \@nameuse{ifspx@#1@insetshadow}% + \spx@boxes@insetshadowtrue + \else + \spx@boxes@insetshadowfalse + \fi + % + \@nameuse{ifspx@#1@withbordercolor}% + \spx@boxes@withbordercolortrue + \sphinxcolorlet{spx@boxes@bordercolor}{sphinx#1BorderColor}% + \else + \spx@boxes@withbordercolorfalse + \fi + % + \@nameuse{ifspx@#1@withbackgroundcolor}% + \spx@boxes@withbackgroundcolortrue + \sphinxcolorlet{spx@boxes@backgroundcolor}{sphinx#1BgColor}% + \else + \spx@boxes@withbackgroundcolorfalse + \fi + % + \@nameuse{ifspx@#1@withshadowcolor}% + \spx@boxes@withshadowcolortrue + \sphinxcolorlet{spx@boxes@shadowcolor}{sphinx#1ShadowColor}% + \else + \spx@boxes@withshadowcolorfalse + \fi + % Display elements pre, topic, warning et al. by default do not include + % shadow in box (legacy; and only topic actually uses a shadow per default) + % This may be refactored still more in future, but this 6.2.0 extra helped + % reduce workload from code-blocks (pre), contents (topic) and admonitions. + % As this conditional is a priori false and should only be changed locally + % (by \sphinxbox), this line is actually superfluous. + \spx@boxes@shadowinbboxfalse + \spx@boxes@fcolorbox@setup@fcolorbox +} +\@ifpackageloaded{pict2e} +{% pict2e is available and loaded + \def\spx@boxes@fcolorbox@setup@fcolorbox{% + \if1% use rounded boxes only if needed (rx>0 iff ry>0) + \ifdim\spx@boxes@radius@topleft@x >\z@0\fi + \ifdim\spx@boxes@radius@topright@x >\z@0\fi + \ifdim\spx@boxes@radius@bottomright@x>\z@0\fi + \ifdim\spx@boxes@radius@bottomleft@x >\z@0\fi + 1\def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}% + \else + \def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rounded}% + \fi + }% end of definition of setup@fcolorbox in case of presence of pict2e +}% +{% pict2e could not be loaded, we must always use fcolorbox@rectangle + \def\spx@boxes@fcolorbox@setup@fcolorbox{% + \def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}% + }% end of definition of setup@fcolorbox in case of absence of pict2e +}% end of "no pict2e" branch + +%%%%%%%%%%%%%%%% +% Support of box-decoration-break=slice +% +% 6.2.0 has renamed and moved this here from sphinxlatexliterals.sty, +% to facilitate supporting box-decoration-break=slice for all directives, +% not only code-block. +% +% It also modified when these post actions are executed, in order +% for openboth to be able to trigger usage of fcolorbox@rectangle. +% So now openbottom and opentop also take advantage of this possible +% optimization. +\def\spx@boxes@fcolorbox@setup@openbottom{% + \spx@boxes@border@bottom \z@ + \spx@boxes@radius@bottomright@x\z@ \spx@boxes@radius@bottomright@y\z@ + \spx@boxes@radius@bottomleft@x \z@ \spx@boxes@radius@bottomleft@y \z@ + \spx@boxes@fcolorbox@setup@fcolorbox +}% +\def\spx@boxes@fcolorbox@setup@opentop{% + \spx@boxes@border@top \z@ + \spx@boxes@radius@topright@x\z@ \spx@boxes@radius@topright@y\z@ + \spx@boxes@radius@topleft@x \z@ \spx@boxes@radius@topleft@y \z@ + \spx@boxes@fcolorbox@setup@fcolorbox +}% +\def\spx@boxes@fcolorbox@setup@openboth{% + \spx@boxes@border@top \z@ + \spx@boxes@border@bottom \z@ + \spx@boxes@radius@bottomright@x\z@ \spx@boxes@radius@bottomright@y\z@ + \spx@boxes@radius@bottomleft@x \z@ \spx@boxes@radius@bottomleft@y \z@ + \spx@boxes@radius@topright@x\z@ \spx@boxes@radius@topright@y\z@ + \spx@boxes@radius@topleft@x \z@ \spx@boxes@radius@topleft@y \z@ + \def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}% +}% + +%%%%%%%%%%%%%%%% +% \sphinxbox (added at 6.2.0) +% +% For an inline box, possibly rounded. +\newcommand\sphinxbox[1][]{% #1 stands for the options, they are... optional! + % \leavevmode makes sure TeX switches to paragraph mode, which is necessary + % if this is first in a paragraph or a list element. The \sphinxAtStartPar + % mechanism also ensures this automatically, if not redefined, but not with + % lualatex as then it is by default doing nothing. + \leavevmode + \begingroup + \ifcsname spx@boxes@sphinxbox@isnested\endcsname + % nested boxes reset all box options to be as the \sphinxboxsetup + % defaults, before applying their specific options + \spx@boxes@sphinxbox@reset + \else + % top layer box, toggle the nested flag + \csname spx@boxes@sphinxbox@isnested\endcsname + \fi + % we do not use \sphinxboxsetup as it is a user command extending the + % "reset" storage + \setkeys{sphinxbox}{#1}% + \spx@boxes@fcolorbox@setup{box}% + \spx@boxes@shadowinbboxtrue% inline sphinx boxes include shadow in bbox + \ifspx@box@withtextcolor\color{sphinxboxTextColor}\fi + % + % MEMO: the fcolorbox@{rectangle,rounded} draw the contents (which here + % will be encapsulated as \box\z@) last, i.e. after shadow, background, + % and border and their color commands. The \reset@color from naked + % top-level \color commands in argument (which can not arise from Sphinx + % mark-up anyhow) would end up being placed via color.sty \aftergroup core + % mechanism in token stream after \spx@boxes@sphinxbox@a (which is the + % first \aftergroup) hence after the box contents with its unbalanced + % color pushes is shipped to PDF. So the missing color pop specials are + % inserted then in correct order at correct place (after the \endgroup at + % end of \spx@boxes@sphinxbox@a but this is not relevant) and do not end + % up causing havoc in push/pop pairs (and all this happens on same page). + % + % There is thus no reason here to go to the trouble to add an extra + % \color@begingroup/\color@endgroup or like pair to encapsulate the caught + % contents in order for the \box\z@ to contain as many color pop's as it + % has color pushes. But as this is subtle, this comment was added for + % future maintenance. Actually even if the contents were not drawn last, + % their (purely theoretical, as Sphinx mark-up can not create it) missing + % color pop's would not have caused trouble I guess as long as the color + % insertions for shadow, background, border are correctly balanced. + \setbox0\hbox\bgroup\aftergroup\spx@boxes@sphinxbox@a + \afterassignment\spx@box@TeXextras + \let\next=% +} +\def\spx@boxes@sphinxbox@a{\spx@boxes@fcolorbox{% + \ifspx@opt@box@addstrut\strut\fi\box\z@}\endgroup} + +\newcommand\newsphinxbox[2][]{% + \newcommand#2[1][]{\sphinxbox[#1,##1]}% +} +% Let's catch \renewsphinxbox[...]{\sphinxbox} which would cause \sphinxbox +% to fall into infinite looping on use. +\newcommand\renewsphinxbox[2][]{% + \in@{#2}{\sphinxbox}% + \ifin@ + \PackageWarning{sphinx}{Attempt to \string\renewsphinxbox\space + the \string\sphinxbox\space command\MessageBreak + itself. This is not allowed and will be ignored.\MessageBreak + Reported}% + \else + \renewcommand#2[1][]{\sphinxbox[#1,##1]}% + \fi +} + +%%%%%%%%%%%%%%%% +% MACROS +% +% \spx@boxes@fcolorbox expands either to \spx@boxes@fcolorbox@rectangle +% or \spx@boxes@fcolorbox@rounded depending on preliminary set-up. +% +% This is decided by the "setup" which must have been executed by the caller. +% Let's give it some (thus unneeded) default fall-back for clarity. +\def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle} +% +% A macro \spx@boxes@fcolorbox@setuphook used to be executed at start of the +% \hbox constructs (rectangle or rounded). This was used until 6.2.0 for the +% support of pre_box-decoration-break option, hence was really an internal +% non-public macro. As it is not needed anymore, with some hesitation it got +% entirely removed at 6.2.0 on the occasion of a refactoring of interactions of +% this file with sphinxlatexliterals.sty. Besides its name should have been +% rather something such as \spx@boxes@fcolorbox@atstartofhbox. +% +% After "setup", \spx@boxes@fcolorbox expands to one of: +% +% - \spx@boxes@fcolorbox@rectangle (4 padding parameters, 4 border widths, 2 shadow widths, +% and three colours: background, border and shadow; same as in CSS styling) +% +% It branches to one of: +% - \spx@boxes@fcolorbox@externalshadow +% - \spx@boxes@fcolorbox@insetshadow (same concept of "inset" as in CSS styling) +% +% - \spx@boxes@fcolorbox@rounded: rounded corners using the picture environment +% and pict2e package for its low-weight interface to PDF graphics operations + +% MEMO: we have also successfully tested usage of tcolorbox.sty (its \tcbox) but +% decided to use pict2e.sty for the following reasons: +% 1- PDF build was observed to be an order of magnitude faster, +% 2- the boxes we can do with pict2e appear to be fancy enough, +% almost matching what one can see in HTML renderings, +% 2- orders of magnitude smaller dependency (tcolorbox uses the pgf TeX +% framework), although on Ubuntu it seems texlive-pictures is +% needed which also contains the whole of pgf/TikZ... so this point +% is a bit moot... + +% For code-blocks, attachments of caption and continuation hints are done +% exactly as prior to extension of Sphinx via this package, whether the box +% has straight or rounded corners. The vertical space occupied is the same, +% if nothing else is changed (perhaps in future the title itself could be also +% rendered in a rounded box?) + +%%%%%%%% +%//// \spx@boxes@fcolorbox@rectangle +% +% This box will have the same baseline as its argument (which is typeset in +% horizontal mode). It takes into account four border widths parameters, four +% padding parameters, two shadow widths (each possibly negative), and three +% colors: background, border and shadow. Its boundary box takes into account +% border and padding. Width of shadow is taken into account if the boolean +% \ifspx@boxes@shadowinbbox is \iftrue. The "setup" sets it to \iffalse. +% Prior to 6.2.0, shadow size was included in bbox but the callers manually +% removed it by extra steps. The \sphinxbox command sets it to \iftrue after +% the "setup". +% +% It is up to the caller to take extra steps if the border and padding must go +% into margin as well (see sphinxlatexliterals.sty for how this is done in +% \spx@verb@FrameCommand). +% +% In usage as a "FrameCommand" with framed.sty, the argument will already be a +% collection of TeX boxes (and interline glues). +% +% This was designed so that the parameters configured by "setup" are +% interpreted as they would be as CSS properties in an HTML context. +\long\def\spx@boxes@fcolorbox@rectangle#1{% + \hbox\bgroup + \setbox\spx@tempboxa + \hbox{\kern\dimexpr\spx@boxes@border@left+\spx@boxes@padding@left\relax + {#1}% + \kern\dimexpr\spx@boxes@padding@right+\spx@boxes@border@right\relax}% + \ht\spx@tempboxa + \dimexpr\ht\spx@tempboxa+\spx@boxes@border@top+\spx@boxes@padding@top\relax + \dp\spx@tempboxa + \dimexpr\dp\spx@tempboxa+\spx@boxes@padding@bottom+\spx@boxes@border@bottom\relax + \ifspx@boxes@insetshadow + \expandafter\spx@boxes@fcolorbox@insetshadow + \else + \expandafter\spx@boxes@fcolorbox@externalshadow + \fi +} + +% external shadow +\def\spx@boxes@fcolorbox@externalshadow{% + % reserve space to external shadow if on left + \ifspx@boxes@withshadow + \ifspx@boxes@shadowinbbox + \ifdim\spx@boxes@shadow@xoffset<\z@\kern-\spx@boxes@shadow@xoffset\fi + \fi + \fi + % BACKGROUND + % draw background and move back to reference point + \ifspx@boxes@withbackgroundcolor + {\color{spx@boxes@backgroundcolor}% + \vrule\@height\ht\spx@tempboxa + \@depth\dp\spx@tempboxa + \@width\wd\spx@tempboxa + \kern-\wd\spx@tempboxa + }% + \fi + % BOX SHADOW + % draw shadow and move back to reference point + \ifspx@boxes@withshadow + \vbox{% + \moveright\spx@boxes@shadow@xoffset + \hbox{\lower\spx@boxes@shadow@yoffset + \vbox{\ifspx@boxes@withshadowcolor + \color{spx@boxes@shadowcolor}% + \else + % 6.2.0: guard against a manually inserted \color command in + % contents which could leak at a page break to the shadow + \normalcolor + \fi + \ifdim\spx@boxes@shadow@yoffset<\z@ + \hrule\@height-\spx@boxes@shadow@yoffset + \kern\spx@boxes@shadow@yoffset + \fi + \setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa{% + \ifdim\spx@boxes@shadow@xoffset<\z@\vrule\@width-\spx@boxes@shadow@xoffset\fi + \hss + \ifdim\spx@boxes@shadow@xoffset>\z@\vrule\@width\spx@boxes@shadow@xoffset\fi + }% + \ht\spx@tempboxb\ht\spx@tempboxa + \dp\spx@tempboxb\dp\spx@tempboxa + \box\spx@tempboxb + \ifdim\spx@boxes@shadow@yoffset>\z@ + \kern-\spx@boxes@shadow@yoffset + \hrule\@height\spx@boxes@shadow@yoffset + \fi + \kern-\dp\spx@tempboxa + }% end of \vbox, attention it will have zero depth if yoffset>0 + \kern-\wd\spx@tempboxa + \ifdim\spx@boxes@shadow@xoffset>\z@ + \kern-\spx@boxes@shadow@xoffset + \fi + }% end of \hbox, attention its depth is only yoffset if yoffset>0 + }% end of \vbox + \fi % end of shadow drawing, and we are back to horizontal reference point + % BOX BORDER + \vbox{\ifspx@boxes@withbordercolor + \color{spx@boxes@bordercolor}% + \else + % 6.2.0: guard against a \color command in contents whose effect + % could leak to border at a pagebreak + \normalcolor + \fi + \hrule\@height\spx@boxes@border@top + \kern-\spx@boxes@border@top + \setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa + {\vrule\@width\spx@boxes@border@left + \hss\vrule\@width\spx@boxes@border@right + }% + \ht\spx@tempboxb\ht\spx@tempboxa + \dp\spx@tempboxb\dp\spx@tempboxa + \box\spx@tempboxb + \kern-\spx@boxes@border@bottom + \hrule\@height\spx@boxes@border@bottom + \kern-\dp\spx@tempboxa + }% attention this box has zero depth due to \hrule at bottom + % step back to horizontal reference point + \kern-\wd\spx@tempboxa + % end of border drawing + % CONTENTS + % adjust the total depth to include the bottom shadow + \ifspx@boxes@withshadow + \ifdim\spx@boxes@shadow@yoffset>\z@ + \dp\spx@tempboxa\dimexpr\dp\spx@tempboxa+\spx@boxes@shadow@yoffset\relax + \fi + \fi + \box\spx@tempboxa + % include lateral shadow in total width + \ifspx@boxes@withshadow + \ifspx@boxes@shadowinbbox + \ifdim\spx@boxes@shadow@xoffset>\z@\kern\spx@boxes@shadow@xoffset\fi + \fi + \fi + \egroup +} + +% inset shadow +% +% The parameters signs are interpreted as in CSS styling. +\def\spx@boxes@fcolorbox@insetshadow{% + % BACKGROUND + % draw background and move back to reference point + \ifspx@boxes@withbackgroundcolor + {\color{spx@boxes@backgroundcolor}% + \vrule\@height\ht\spx@tempboxa + \@depth\dp\spx@tempboxa + \@width\wd\spx@tempboxa + \kern-\wd\spx@tempboxa + }% + \fi + % BOX SHADOW + % draw shadow and move back to reference point + \ifspx@boxes@withshadow + \hbox{\vbox{\ifspx@boxes@withshadowcolor + \color{spx@boxes@shadowcolor}% + \else + % 6.2.0: guard against a manually inserted \color command in + % contents which could leak at a page break to the shadow + \normalcolor + \fi +% NOTA BENE +% We deliberately draw shadow partially under an area later covered by frame +% with the idea to avoid anti-aliasing problems but in fact this may be a bad +% idea with border is thin. +% This may need some extra testing with PDF viewers... reports welcome! + \ifdim\spx@boxes@shadow@yoffset>\z@ + \hrule\@height\dimexpr\spx@boxes@border@top+\spx@boxes@shadow@yoffset\relax + \kern-\spx@boxes@shadow@yoffset + \kern-\spx@boxes@border@top + \fi + \setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa{% + \ifdim\spx@boxes@shadow@xoffset>\z@ + \vrule\@width\dimexpr\spx@boxes@border@left+\spx@boxes@shadow@xoffset\relax\fi + \hss + \ifdim\spx@boxes@shadow@xoffset<\z@ + \vrule\@width\dimexpr-\spx@boxes@shadow@xoffset+\spx@boxes@border@right\relax\fi + }% + \ht\spx@tempboxb\ht\spx@tempboxa + \dp\spx@tempboxb\dp\spx@tempboxa + \box\spx@tempboxb + \ifdim\spx@boxes@shadow@yoffset<\z@ + \kern\spx@boxes@shadow@yoffset + \kern-\spx@boxes@border@bottom + \hrule\@height\dimexpr-\spx@boxes@shadow@yoffset+\spx@boxes@border@bottom\relax + \fi + \kern-\dp\spx@tempboxa + }% end of \vbox, attention it will have zero depth if yoffset<0 + \kern-\wd\spx@tempboxa + }% end of \hbox, attention its depth is only |yoffset| if yoffset<0 + \fi % end of inset shadow drawing, and we are back to horizontal reference point + % BOX BORDER + \vbox{\ifspx@boxes@withbordercolor + \color{spx@boxes@bordercolor}% + \else + % 6.2.0: guard against a \color command in contents whose effect + % could leak to border at a pagebreak + \normalcolor + \fi + \hrule\@height\spx@boxes@border@top + \kern-\spx@boxes@border@top + \setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa + {\vrule\@width\spx@boxes@border@left + \hss\vrule\@width\spx@boxes@border@right + }% + \ht\spx@tempboxb\ht\spx@tempboxa + \dp\spx@tempboxb\dp\spx@tempboxa + \box\spx@tempboxb + \kern-\spx@boxes@border@bottom + \hrule\@height\spx@boxes@border@bottom + \kern-\dp\spx@tempboxa + }% attention this box has zero depth due to \hrule at bottom + % step back to horizontal reference point + \kern-\wd\spx@tempboxa + % end of border drawing + % CONTENTS + \box\spx@tempboxa + \egroup +} + +% let's abort input if pict2e package could not be loaded. +% To be extra safe we also alias @rounded to @rectangle but +% a priori the architecture is done so that @rounded will never +% be called in that case by other Sphinx LaTeX components. +\@ifpackageloaded{pict2e} + {} + {\def\spx@boxes@fcolorbox@rounded{\spx@boxes@fcolorbox@rectangle}% + \endinput + } + +% we proceed now in the context of pict2e being available and loaded +% (TeX being a macro-expansion based language it would have +% swallowed all the coming definitions even if pict2e +% had in fact not been loaded... but we aborted the input above) +%%%%%%%% +%//// \spx@boxes@fcolorbox@rounded +% +% Prior to 6.2.0, a constant border-width was applied as the border was +% obtained as a \strokepath. This allowed 4 distinct radii but not to vary the +% border widths. Now the border is drawn by two \fillpath operation, the first +% one filling up to external border, the second one actually filling for the +% background paradoxically on top of it, up to internal border path. +% +% This 6.2.0 abandonment of \strokepath allowed great simplification in +% supporting opentop, openbottom and openboth situations, and it can +% allow automatic support of openleft and openright analogs. +% +% And 6.2.0 also implements elliptical arcs thanks to ellipse package, +% which extends pict2e. + +% Currently, inset shadow is not supported. +% +% Prior to 6.2.0 an inset shadow triggered the rectangle variant, so we never +% ended here, but now it is simply ignored. This change does not appear to me +% to be breaking, as it changes output only for conf.py's specifying both +% rounded corners and an inset shadow and the documentation said it was +% incompatible. + +% wrappers for pict2e usage if old +% Better not to copy over 2020 pict2e definitions in case +% something internal changes +% However our wrappers will work ONLY with dimensional inputs +% No need to pre-expand the arguments +% Braces in case the expression uses parentheses +\def\spx@moveto(#1,#2){\moveto({\strip@pt\dimexpr#1\relax},{\strip@pt\dimexpr#2\relax})} +\def\spx@lineto(#1,#2){\lineto({\strip@pt\dimexpr#1\relax},{\strip@pt\dimexpr#2\relax})} +% attention here the [N] becomes mandatory +% \circlearc[<N>]{<X>}{<Y>}{<RAD>}{<ANGLE1>}{<ANGLE2>} +\def\spx@circlearc[#1]#2#3#4%#5#6 + {\circlearc[#1]{\strip@pt\dimexpr#2\relax}% + {\strip@pt\dimexpr#3\relax}% + {\strip@pt\dimexpr#4\relax}% + } +% attention here too the [N] becomes mandatory +% the core path macro of ellipse.sty. Thanks to Daan Leijen, author of this +% package. +% \elliparc [<initial>]{<center-x>}{<center-y>}{<x-rad>}{<y-rad>}{<start-angle>}{<end-angle>} +% maybe this wrapper is unneeded but I don't have real time to check +\def\spx@elliparc[#1]#2#3#4#5%#6#7 + {\elliparc[#1]{\strip@pt\dimexpr#2\relax}% + {\strip@pt\dimexpr#3\relax}% + {\strip@pt\dimexpr#4\relax}% + {\strip@pt\dimexpr#5\relax}% + } + +% Macro whose execution prepares a path to be either stroked or filled +% Only fill operation is used at 6.2.0. The radii are given by the set box +% parameters, but the width and height are in \spx@width and \spx@height. A +% \put command will be used for appropriate shifts. +% 6.2.0 adds elliptical corners! +% But I feel perhaps I need to think about how x-radius and y-radius should +% interact with border-width. So consider output WIP for time being. +\def\spx@boxes@border@defpath{% + \spx@moveto(\spx@boxes@radius@bottomleft@x,\z@)% our \spx@moveto is a bit rigid + % and we must use \z@ not 0 here + \spx@lineto(\spx@width-\spx@boxes@radius@bottomright@x,\z@)% + % x and y radii are either both positive or both zero + % probably not needed to actually guard against the latter case, + % let's do it nevertheless + \ifdim\spx@boxes@radius@bottomright@x>\z@ + \ifdim\spx@boxes@radius@bottomright@x=\spx@boxes@radius@bottomright@y + \spx@circlearc[2]{\spx@width-\spx@boxes@radius@bottomright@x}% + {\spx@boxes@radius@bottomright@y}% + {\spx@boxes@radius@bottomright@x}{-90}{0}% + \else + \spx@elliparc[2]{\spx@width-\spx@boxes@radius@bottomright@x}% + {\spx@boxes@radius@bottomright@y}% + {\spx@boxes@radius@bottomright@x} + {\spx@boxes@radius@bottomright@y}{-90}{0}% + \fi + \fi + \spx@lineto(\spx@width,% + \spx@height-\spx@boxes@radius@topright@y)% + \ifdim\spx@boxes@radius@topright@x>\z@ + \ifdim\spx@boxes@radius@topright@x=\spx@boxes@radius@topright@y + \spx@circlearc[2]{\spx@width-\spx@boxes@radius@topright@x} + {\spx@height-\spx@boxes@radius@topright@y}% + {\spx@boxes@radius@topright@x}{0}{90}% + \else + \spx@elliparc[2]{\spx@width-\spx@boxes@radius@topright@x} + {\spx@height-\spx@boxes@radius@topright@y}% + {\spx@boxes@radius@topright@x}% + {\spx@boxes@radius@topright@y}{0}{90}% + \fi + \fi + \spx@lineto(\spx@boxes@radius@topleft@x,\spx@height)% + \ifdim\spx@boxes@radius@topleft@x>\z@ + \ifdim\spx@boxes@radius@topleft@x=\spx@boxes@radius@topleft@y + \spx@circlearc[2]{\spx@boxes@radius@topleft@x}% + {\spx@height-\spx@boxes@radius@topleft@y}% + {\spx@boxes@radius@topleft@x}{90}{180}% + \else + \spx@elliparc[2]{\spx@boxes@radius@topleft@x}% + {\spx@height-\spx@boxes@radius@topleft@y}% + {\spx@boxes@radius@topleft@x}% + {\spx@boxes@radius@topleft@y}{90}{180}% + \fi + \fi + \spx@lineto(\z@,\spx@boxes@radius@bottomleft@y)% + \ifdim\spx@boxes@radius@bottomleft@x>\z@ + \ifdim\spx@boxes@radius@bottomleft@x=\spx@boxes@radius@bottomleft@y + \spx@circlearc[2]{\spx@boxes@radius@bottomleft@x}% + {\spx@boxes@radius@bottomleft@y}% + {\spx@boxes@radius@bottomleft@x}{180}{270}% + \else + \spx@elliparc[2]{\spx@boxes@radius@bottomleft@x}% + {\spx@boxes@radius@bottomleft@y}% + {\spx@boxes@radius@bottomleft@x}% + {\spx@boxes@radius@bottomleft@y}{180}{270}% + \fi + \fi +}% end of definition of \spx@boxes@border@defpath + +% The customization of the various parameters must have been done via an +% appropriate call to \spx@boxes@fcolorbox@setup, which will have set up +% \spx@boxes@fcolorbox to expand to \spx@boxes@fcolorbox@rounded, and will +% have set its various parameters. +% +\long\def\spx@boxes@fcolorbox@rounded #1{% + \hbox{% + \ifspx@boxes@withshadow + \ifspx@boxes@insetshadow + \spx@boxes@withshadowfalse % ignore inset shadow + \fi + \fi + % reserve space to external shadow if on left + \ifspx@boxes@withshadow + \ifspx@boxes@shadowinbbox + \ifdim\spx@boxes@shadow@xoffset<\z@\kern-\spx@boxes@shadow@xoffset\fi + \fi + \fi + \vbox{% + % adjust vertical bbox + \ifspx@boxes@withshadow + \ifdim\spx@boxes@shadow@yoffset<\z@ + \kern-\spx@boxes@shadow@yoffset + \fi + \fi + \setlength{\unitlength}{1pt}% + \setbox\spx@tempboxa + \hbox{\kern\dimexpr\spx@boxes@border@left+\spx@boxes@padding@left\relax + {#1}% + \kern\dimexpr\spx@boxes@padding@right+\spx@boxes@border@right\relax}% + \ht\spx@tempboxa + \dimexpr\ht\spx@tempboxa+\spx@boxes@border@top+\spx@boxes@padding@top\relax + \dp\spx@tempboxa + \dimexpr\dp\spx@tempboxa+\spx@boxes@padding@bottom+\spx@boxes@border@bottom\relax + \edef\spx@width{\number\wd\spx@tempboxa sp}% + \edef\spx@height{\number\dimexpr\ht\spx@tempboxa+\dp\spx@tempboxa sp}% + \hbox{% + \begin{picture}% + % \strip@pt\dimexpr to work around "old" LaTeX picture limitation + % (we could use the "picture" package, this would add another dependency) + (\strip@pt\dimexpr\spx@width\relax,\strip@pt\dimexpr\spx@height\relax)% + \spx@boxes@border@defpath + \ifspx@boxes@withshadow + \ifspx@boxes@withshadowcolor + \color{spx@boxes@shadowcolor}% + \else + % 6.2.0: here and elsewhere guard against a manually inserted + % \color command in contents which could leak to the shadow + % to the shadow + \normalcolor + \fi + \put(\strip@pt\spx@boxes@shadow@xoffset,% + \strip@pt\dimexpr-\spx@boxes@shadow@yoffset\relax) + {\fillpath}% + \fi + \spx@boxes@border@defpath% must be redone after each \fillpath! (even if + % was in a \put) + \ifspx@boxes@withbordercolor + \color{spx@boxes@bordercolor}% + \else + \normalcolor + \fi + \fillpath + \ifspx@boxes@withbackgroundcolor + \color{spx@boxes@backgroundcolor}% + \else + \color{white}% + \fi + \edef\spx@width{\number\dimexpr\spx@width-\spx@boxes@border@left + -\spx@boxes@border@right sp}% + \edef\spx@height{\number\dimexpr\spx@height-\spx@boxes@border@top + -\spx@boxes@border@bottom sp}% + % redefine a path (in relative coordinates) matching the area delimited + % by the internal borders + \spx@boxes@border@defpath + % use \put to shift, and fill it with background color + \put(\strip@pt\spx@boxes@border@left,\strip@pt\spx@boxes@border@bottom) + {\fillpath}% + \end{picture}}% end of picture \hbox in \vbox + % back-up vertically for outputting the contents + \kern-\dimexpr\ht\spx@tempboxa+\dp\spx@tempboxa\relax + % adjust vertical bbox + \ifspx@boxes@withshadow + \ifdim\spx@boxes@shadow@yoffset>\z@ + \dp\spx@tempboxa\dimexpr\dp\spx@tempboxa+\spx@boxes@shadow@yoffset\relax + \fi + \fi + % inhibit TeX's "line skip" adjustment when piling up hboxes in a vbox + \nointerlineskip + \box\spx@tempboxa + }% end of \vbox + % include lateral shadow in total width + \ifspx@boxes@withshadow + \ifspx@boxes@shadowinbbox + \ifdim\spx@boxes@shadow@xoffset>\z@\kern\spx@boxes@shadow@xoffset\fi + \fi + \fi + }% end of \hbox +}% + + +\endinput |