Skip to content

Commit

Permalink
LaTeX: optional rounded corners for framing of code-blocks
Browse files Browse the repository at this point in the history
Via a new configuration verbatimradius of 'sphinxsetup', which defaults
to 0pt.

If this dimension is non zero, the LaTeX package pict2e will be loaded
to help construct frames with rounded corners for code-blocks.  And if
the LaTeX package pict2e was not found, a LaTeX warning is issued during
PDF build.
  • Loading branch information
jfbu committed Jul 5, 2022
1 parent d4c8e84 commit 4dbb62b
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 3 deletions.
5 changes: 5 additions & 0 deletions doc/conf.py
Expand Up @@ -74,6 +74,11 @@
{\footnotesize\raggedright\printindex}
{\begin{sphinxtheindex}\end{sphinxtheindex}}
''',
'sphinxsetup': """%
VerbatimColor={RGB}{242,242,242},%
VerbatimBorderColor={RGB}{32,32,32},%
verbatimradius=3pt%
""",
}
latex_show_urls = 'footnote'
latex_use_xindy = True
Expand Down
45 changes: 42 additions & 3 deletions doc/latex.rst
Expand Up @@ -8,8 +8,11 @@ LaTeX customization

\begingroup
\sphinxsetup{%
verbatimwithframe=false,
verbatimborder=2pt,
verbatimsep=5pt,
verbatimradius=5pt,
VerbatimColor={named}{OldLace},
VerbatimBorderColor={named}{Gold},
TitleColor={named}{DarkGoldenrod},
hintBorderColor={named}{LightCoral},
attentionborder=3pt,
Expand Down Expand Up @@ -580,8 +583,17 @@ start of the chapter::

\begingroup
\sphinxsetup{%
verbatimwithframe=false,
% These were used as defaults for the whole sphinx.pdf
% VerbatimColor={RGB}{242,242,242},%
% VerbatimBorderColor={RGB}{32,32,32},%
% verbatimradius=3pt,%
% New definitions for this chapter code-blocks only:
VerbatimColor={named}{OldLace},
VerbatimBorderColor={named}{Gold},
verbatimradius=5pt,
verbatimsep=5pt,
verbatimborder=2pt,
% Other configuration for this chapter only:
TitleColor={named}{DarkGoldenrod},
hintBorderColor={named}{LightCoral},
attentionborder=3pt,
Expand All @@ -593,7 +605,8 @@ start of the chapter::
cautionBorderColor={named}{Cyan},
cautionBgColor={named}{LightCyan}}

The below is included at the end of the chapter::
And this is placed at the end of the chapter source to end the scope of
the configuration::

.. raw:: latex

Expand Down Expand Up @@ -839,6 +852,32 @@ Do not use quotes to enclose values, whether numerical or strings.

Default: ``\fboxrule``

``verbatimradius``
The radius of the rounded corners of the frame around :rst:dir:`code-block`\ s.

Default: ``0pt``

.. versionadded:: 5.1.0

If non-zero, it will trigger the loading of LaTeX package pict2e_.

.. caution::

The interface will remain experimental during the 5.x cycle: the
feature itself will remain, but the interface may evolve to include
other display elements such as admonitions. For the latter it is
actually already possible for LaTeX-expert Sphinx users to use
functionalities of LaTeX packages such as tcolorbox_, via
redefinitions of the ``sphinxheavybox`` and ``sphinxlightbox``
`Environments`_. This would be more difficult for code-blocks, and
this key achieves it. The pict2e_ interface to some basic PDF
graphics operations is much more light-weight than the pgf_
framework used by tcolorbox_.

.. _pict2e: https://ctan.org/pkg/pict2e
.. _tcolorbox: https://ctan.org/pkg/tcolorbox
.. _pgf: https://ctan.org/pkg/pgf

``shadowsep``
The separation between contents and frame for :dudir:`contents` and
:dudir:`topic` boxes.
Expand Down
10 changes: 10 additions & 0 deletions sphinx/texinputs/sphinx.sty
Expand Up @@ -74,6 +74,7 @@
% dimensions, we declare the \dimen registers here.
\newdimen\sphinxverbatimsep
\newdimen\sphinxverbatimborder
\newdimen\sphinxverbatimradius
\newdimen\sphinxshadowsep
\newdimen\sphinxshadowsize
\newdimen\sphinxshadowrule
Expand All @@ -87,6 +88,12 @@
\define@key{sphinx}{verbatimsep}{\sphinxverbatimsep\dimexpr #1\relax}
\sphinxverbatimborder=\fboxrule
\define@key{sphinx}{verbatimborder}{\sphinxverbatimborder\dimexpr #1\relax}
\sphinxverbatimradius=0pt
\define@key{sphinx}{verbatimradius}{%
\sphinxverbatimradius\dimexpr #1\relax
\ifdim\sphinxverbatimradius=\z@\else\RequirePackage{sphinxpackageboxes}\fi
}
\AtBeginDocument{\define@key{sphinx}{verbatimradius}{\sphinxverbatimradius\dimexpr #1\relax}}
% topic boxes
\sphinxshadowsep =5pt
\define@key{sphinx}{shadowsep}{\sphinxshadowsep\dimexpr #1\relax}
Expand Down Expand Up @@ -274,6 +281,9 @@
\input{sphinxlatexadmonitions.sty}
\input{sphinxlatexliterals.sty}
\input{sphinxlatexshadowbox.sty}
\ifdim\sphinxverbatimradius=\z@\else
\RequirePackage{sphinxpackageboxes}
\fi


%% CONTAINERS
Expand Down
113 changes: 113 additions & 0 deletions sphinx/texinputs/sphinxpackageboxes.sty
@@ -0,0 +1,113 @@
%% COLORED BOXES
%
% change this info string if making any custom modification
\ProvidesPackage{sphinxpackageboxes}[2022/07/04 v5.1.0 advanced colored boxes]

% Currently, this file only provides a replacement to the \spx@verb@fcolorbox
% of sphinxlatexliterals.sty which will draw boxes with a frame having
% rounded corners, and a background color.
%
% It needs \sphinxverbatimsep, \sphinxverbatimborder and a new parameter
% \sphinxverbatimradius
%
% Executes \RequirePackage for:
%
% - pict2e. Ideally we would need a recent version of this package which
% allows dimensional arguments to its \moveto, \lineto, etc...
% but we add ourselves some wrapper to facilitate the usage.


% MEMO: we have also successfully tested usage of tcolorbox's \tcbox but
% decided to use pict2e.sty for the following reasons:
% 1- an order of magnitude faster for what we want to do,
% 2- orders of magnitude smaller dependency (tcolorbox uses the pgf TeX
% framework)
% 3- possibility to accomplish already quite fancy boxes with pict2e
% (and the additional coding as contributed here).

% In this first installment, the caption and continuation hints of code-blocks
% are done exactly as formerly; only difference is in the rounded corrners.
% The space occupied is same, if nothing else is changed.

\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
The verbatimradius setting will thus be ignored}%
\AtEndDocument{\PackageWarningNoLine{sphinx}{%
I issued a warning which may have gotten lost in the\MessageBreak
gigantic console output: pict2e.sty was not found,\MessageBreak
and verbatimradius has been ignored}}\endinput}

% First we define some wrapper to be able to use arguments being (only)
% dimensions or dimensional expressions. The \unitlength will always be 1pt.
\def\spx@moveto(#1,#2)%
{\expanded{\noexpand\moveto(\strip@pt\dimexpr#1,\strip@pt\dimexpr#2)}}
\def\spx@lineto(#1,#2)%
{\expanded{\noexpand\lineto(\strip@pt\dimexpr#1,\strip@pt\dimexpr#2)}}
% attention we use here [2] always; and there are two more mandatory
% arguments, angles, we don't need to worry about them here.
\def\spx@circlearc#1#2#3{\expanded{\noexpand\circlearc[2]%
{\strip@pt\dimexpr#1}{\strip@pt\dimexpr#2}{\strip@pt\dimexpr#3}}%
}

% TODO: add top right bottom left padding possibilities.
\long\def\spx@verb@fcolorbox #1#2#3{%
% Prepare a box with the contents and reserved space for framing.
\setbox\tw@\hbox{\kern\dimexpr\sphinxverbatimborder+\sphinxverbatimsep\relax
{#3}\kern\dimexpr\sphinxverbatimborder+\sphinxverbatimsep\relax}%
\ht\tw@ \dimexpr\ht\tw@+\sphinxverbatimsep+\sphinxverbatimborder\relax
\dp\tw@ \dimexpr\dp\tw@+\sphinxverbatimsep+\sphinxverbatimborder\relax
\vbox{%
% Prepare a macro for path to be inserted in a picture environment for stroke
% and fill; the path will be redefined for each of fill or stroke. This macro
% does nothing yet.
\def\spx@dopath{%
\spx@moveto(\sphinxverbatimradius,\z@)% \z@ not 0 as our \spx@moveto is quite dumb
\spx@lineto(\wd\tw@-\sphinxverbatimborder-\sphinxverbatimradius,\z@)%
\spx@circlearc{\wd\tw@-\sphinxverbatimborder-\sphinxverbatimradius}%
{\sphinxverbatimradius}%
{\sphinxverbatimradius}{-90}{0}%
\spx@lineto(\wd\tw@-\sphinxverbatimborder,\ht\tw@+\dp\tw@-\sphinxverbatimborder-\sphinxverbatimradius)%
\spx@circlearc{\wd\tw@-\sphinxverbatimborder-\sphinxverbatimradius}
{\ht\tw@+\dp\tw@-\sphinxverbatimborder-\sphinxverbatimradius}%
{\sphinxverbatimradius}{0}{90}%
\spx@lineto(\sphinxverbatimradius,\ht\tw@+\dp\tw@-\sphinxverbatimborder)%
\spx@circlearc{\sphinxverbatimradius}%
{\ht\tw@+\dp\tw@-\sphinxverbatimborder-\sphinxverbatimradius}%
{\sphinxverbatimradius}{90}{180}%
\spx@lineto(\z@,\sphinxverbatimradius)%
\spx@circlearc{\sphinxverbatimradius}{\sphinxverbatimradius}{\sphinxverbatimradius}{180}{270}%
}% end of definition of \spx@dopath
%
#1% continuation hint attached above frame
% there will be a small "\lineskip" space here from TeX
% draw frame border _latest_ to avoid pdf viewer issue
% be careful not to cause "color push + contents + color pop"
% MEMO: when pict2e doth a path stroke, the path is in the middle of the line
% width, i.e. the line extends by half its width to the exterior of the filled
% path. This explains some 0.5 things below.
\hbox{\setlength{\unitlength}{1pt}% attention to space token here
\begin{picture}(\wd\tw@,\ht\tw@+\dp\tw@)%
(-.5\sphinxverbatimborder,-.5\sphinxverbatimborder)%
\color{VerbatimColor}% color for background
\spx@dopath\fillpath
\color{VerbatimBorderColor}% color for border
\ifspx@opt@verbatimwithframe % even with \sphinxverbatimborder set to 0pt, the
% stroke will produce a visible contour, so we
% must explicitly exclude doing it.
\linethickness{\sphinxverbatimborder}%
\spx@dopath\strokepath
\fi
\end{picture}}%
% now the contents
\kern-\dimexpr\ht\tw@+\dp\tw@\relax
\copy\tw@ % attention that #2 will need \wd\tw@
\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
}%

\endinput

0 comments on commit 4dbb62b

Please sign in to comment.