%% COLOURED BOXES % % change this info string if making any custom modification \ProvidesPackage{sphinxpackageboxes}[2022/07/04 v5.1.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. % Provides box registers \spx@tempboxa, \spx@tempboxb usable in other places \newbox\spx@tempboxa \newbox\spx@tempboxb % Internal dimens, conditionals, and colour parameters to be configured % by callers in "setup" macros \newif\ifspx@boxes@withshadow \newif\ifspx@boxes@insetshadow \newif\ifspx@boxes@withbackgroundcolor \newif\ifspx@boxes@withshadowcolor \newif\ifspx@boxes@withbordercolor % \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 % only circular arcs, x-radius same as y-radius \newdimen\spx@boxes@radius@topright \newdimen\spx@boxes@radius@bottomright \newdimen\spx@boxes@radius@bottomleft % % These colours have to be defined appropriately by the callers: % spx@boxes@bordercolor % spx@boxes@backgroundcolor % spx@boxes@shadowcolor %%%%%%%%%%%%%%%% % MACROS % % - \spx@boxes@fcolorbox (4 padding parameters, 4 border widths, 2 shadow widths, % and three colours: background, border and shadow; same as in CSS styling) % % - \spx@boxes@fcolorbox@insetshadow (same 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, attachements 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 % 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 % all of shadow, border and padding. It is up to the caller to take steps for % the shadow (and perhaps also border, and padding) to go into margin or stay % inside the text area, in collaboration with framed.sty. In usage as a % "FrameCommand" with framed.sty, the argument will already be a collection % of TeX boxes (and interline glues). % % The customization of the various parameters are under responsability of % the caller, before exapnsion of \spx@boxes@fcolorbox. % An extra hook is provided: \let\spx@boxes@fcolorbox@setuphook\@empty % % The parameters are interpreted as they would as CSS properties. % For inset shadows see separate \spx@boxes@fcolorbox@insetshadow. \long\def\spx@boxes@fcolorbox#1{% \hbox\bgroup \spx@boxes@fcolorbox@setuphook \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 } \def\spx@boxes@fcolorbox@externalshadow{% % reserve space to shadow if on left \ifspx@boxes@withshadow \ifdim\spx@boxes@shadow@xoffset<\z@\kern-\spx@boxes@shadow@xoffset\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}\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}\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 \ifdim\spx@boxes@shadow@xoffset>\z@\kern\spx@boxes@shadow@xoffset\fi \fi \egroup } %//// \spx@boxes@fcolorbox@insetshadow % The parameters 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}\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}\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 } %%%%%%%% % \spx@boxes@fcolorbox@rounded % % Various radii but only one border-width parameter. % Shadow too. % 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 \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}} % This macro will when executed in a picture environment prepare a path which % is both used for filling backround color and stroking border % The coordinate origin in the LaTeX picture environment will be at half the % border width (d/2, d/2), d = constant border width \def\spx@boxes@borderpath{% \spx@moveto(\spx@boxes@radius@bottomleft,\z@)% \z@ not 0 as our \spx@moveto is quite dumb \spx@lineto(\wd\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@bottomright,\z@)% \spx@circlearc[2]{\wd\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@bottomright}% {\spx@boxes@radius@bottomright}% {\spx@boxes@radius@bottomright}{-90}{0}% \spx@lineto(\wd\spx@tempboxa-\spx@boxes@border,% \ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@topright)% \spx@circlearc[2]{\wd\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@topright} {\ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@topright}% {\spx@boxes@radius@topright}{0}{90}% \spx@lineto(\spx@boxes@radius@topleft,\ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border)% \spx@circlearc[2]{\spx@boxes@radius@topleft}% {\ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@topleft}% {\spx@boxes@radius@topleft}{90}{180}% \spx@lineto(\z@,\spx@boxes@radius@bottomleft)% \spx@circlearc[2]{\spx@boxes@radius@bottomleft}% {\spx@boxes@radius@bottomleft}% {\spx@boxes@radius@bottomleft}{180}{270}% }% end of definition of \spx@boxes@borderpath \def\spx@boxes@borderpath@opentop{% \spx@moveto(\z@,\ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border)% \spx@lineto(\z@,\spx@boxes@radius@bottomleft)% \spx@circlearc[2]{\spx@boxes@radius@bottomleft}% {\spx@boxes@radius@bottomleft}% {\spx@boxes@radius@bottomleft}{180}{270}% \spx@lineto(\wd\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@bottomright,\z@)% \spx@circlearc[2]{\wd\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@bottomright}% {\spx@boxes@radius@bottomright}% {\spx@boxes@radius@bottomright}{-90}{0}% \spx@lineto(\wd\spx@tempboxa-\spx@boxes@border,% \ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border)% }% end of definition of \spx@boxes@borderpath@opentop \def\spx@boxes@borderpath@openbottom{% \spx@moveto(\wd\spx@tempboxa-\spx@boxes@border,\z@)% \spx@lineto(\wd\spx@tempboxa-\spx@boxes@border,% \ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@topright)% \spx@circlearc[2]{\wd\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@topright} {\ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@topright}% {\spx@boxes@radius@topright}{0}{90}% \spx@lineto(\spx@boxes@radius@topleft,\ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border)% \spx@circlearc[2]{\spx@boxes@radius@topleft}% {\ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border-\spx@boxes@radius@topleft}% {\spx@boxes@radius@topleft}{90}{180}% \spx@lineto(\z@,\z@)% }% end of definition of \spx@boxes@borderpath@openbottom \def\spx@boxes@borderpath@openboth{% \spx@moveto(\wd\spx@tempboxa-\spx@boxes@border,\z@)% \spx@lineto(\wd\spx@tempboxa-\spx@boxes@border,% \ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border)% \spx@moveto(\z@,\ht\spx@tempboxa+\dp\spx@tempboxa-\spx@boxes@border)% \spx@lineto(\z@,\z@)% }% end of definition of \spx@boxes@borderpath@openboth \long\def\spx@boxes@fcolorbox@rounded #1{% \hbox{% \spx@boxes@fcolorbox@setuphook % reserve space to shadow if on left \ifspx@boxes@withshadow \ifdim\spx@boxes@shadow@xoffset<\z@\kern-\spx@boxes@shadow@xoffset\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+\spx@boxes@padding@left\relax {#1}% \kern\dimexpr\spx@boxes@padding@right+\spx@boxes@border\relax}% \ht\spx@tempboxa \dimexpr\ht\spx@tempboxa+\spx@boxes@border+\spx@boxes@padding@top\relax \dp\spx@tempboxa \dimexpr\dp\spx@tempboxa+\spx@boxes@padding@bottom+\spx@boxes@border\relax \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\wd\spx@tempboxa,\strip@pt\dimexpr\ht\spx@tempboxa+\dp\spx@tempboxa\relax)% (\strip@pt\dimexpr-.5\spx@boxes@border\relax,\strip@pt\dimexpr-.5\spx@boxes@border\relax)% \ifspx@boxes@withshadow \color{spx@boxes@shadowcolor}% \put(\strip@pt\dimexpr\ifdim\spx@boxes@shadow@xoffset<\z@-\fi 0.5\spx@boxes@border+\spx@boxes@shadow@xoffset\relax,% \strip@pt\dimexpr\ifdim\spx@boxes@shadow@yoffset<\z@\else-\fi 0.5\spx@boxes@border-\spx@boxes@shadow@yoffset\relax) {\spx@boxes@borderpath\fillpath}% {\ifspx@boxes@withbackgroundcolor\else \color{white}% or rather try to use page color? \spx@boxes@borderpath\fillpath \fi}% \fi {\ifspx@boxes@withbackgroundcolor \color{spx@boxes@backgroundcolor}% \spx@boxes@borderpath\fillpath \fi}% \ifdim\spx@boxes@border>\z@ % even with \spx@boxes@border set to 0pt as done if verbatimwithframe=false % stroke will produce a visible contour, so we exclude doing it in that case \ifspx@boxes@withbordercolor \color{spx@boxes@bordercolor}% \fi \linethickness{\spx@boxes@border}% \ifdim\spx@boxes@border@top=\z@ \ifdim\spx@boxes@border@bottom=\z@ \spx@boxes@borderpath@openboth \else \spx@boxes@borderpath@opentop \fi \else \ifdim\spx@boxes@border@bottom=\z@ \spx@boxes@borderpath@openbottom \else\spx@boxes@borderpath\strokepath \fi\fi \strokepath \fi \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 \box\spx@tempboxa }% end of \vbox % include lateral shadow in total width \ifspx@boxes@withshadow \ifdim\spx@boxes@shadow@xoffset>\z@\kern\spx@boxes@shadow@xoffset\fi \fi }% end of \hbox }% \endinput