diff --git a/doc/conf.py b/doc/conf.py index 1bcf5d559e..a721508deb 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -79,7 +79,8 @@ 'sphinxsetup': """% VerbatimColor={RGB}{242,242,242},% VerbatimBorderColor={RGB}{32,32,32},% -verbatimradius=3pt% +pre_border-radius=3pt,% +pre_box-decoration-break=slice,% """, } latex_show_urls = 'footnote' diff --git a/doc/latex.rst b/doc/latex.rst index 4d16445040..c46ab6e29b 100644 --- a/doc/latex.rst +++ b/doc/latex.rst @@ -8,21 +8,26 @@ LaTeX customization \begingroup \sphinxsetup{% - verbatimborder=2pt, - verbatimsep=5pt, - verbatimradius=5pt, - VerbatimColor={named}{OldLace}, - VerbatimBorderColor={named}{Gold}, - TitleColor={named}{DarkGoldenrod}, - hintBorderColor={named}{LightCoral}, - attentionborder=3pt, - attentionBorderColor={named}{Crimson}, - attentionBgColor={named}{FloralWhite}, - noteborder=2pt, - noteBorderColor={named}{Olive}, - cautionborder=3pt, - cautionBorderColor={named}{Cyan}, - cautionBgColor={named}{LightCyan}} + TitleColor={named}{DarkGoldenrod}, + pre_border-width=2pt, + pre_padding=5pt, + pre_border-radius=5pt, + pre_background-TeXcolor={named}{OldLace}, + pre_border-TeXcolor={named}{Gold}, + div.warning_border-width=3pt, + div.warning_padding=6pt, + div.warning_padding-right=18pt, + div.warning_padding-bottom=18pt, + div.warning_border-TeXcolor={named}{DarkCyan}, + div.warning_background-TeXcolor={named}{LightCyan}, + div.warning_box-shadow=-12pt -12pt inset, + div.warning_box-shadow-TeXcolor={named}{Cyan}, + attentionborder=3pt, + attentionBorderColor={named}{Crimson}, + attentionBgColor={named}{FloralWhite}, + noteborder=2pt, + noteBorderColor={named}{Olive}, + hintBorderColor={named}{LightCoral}} \relax Unlike :ref:`the HTML builders `, the ``latex`` builder does not @@ -65,7 +70,10 @@ The ``latex_elements`` configuration setting A dictionary that contains LaTeX snippets overriding those Sphinx usually puts into the generated ``.tex`` files. Its ``'sphinxsetup'`` key is described -:ref:`separately `. +:ref:`separately `. It allows also local configurations +inserted in generated files, via :rst:dir:`raw` directives. For example, in +the PDF documentation this chapter is styled especially, as will be described +later. Keys that you may want to override include: @@ -575,35 +583,48 @@ The colors used in the above are provided by the ``svgnames`` option of the } It is possible to insert further uses of the ``\sphinxsetup`` LaTeX macro -directly into the body of the document, via the help of the :rst:dir:`raw` +directly into the body of the document, via the help of the ``raw`` directive. This chapter is styled in the PDF output using the following at the -start of the chapter:: +start of the chapter (which uses keys described later in :ref:`additionalcss`):: .. raw:: latex \begingroup \sphinxsetup{% - % 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, - attentionBorderColor={named}{Crimson}, - attentionBgColor={named}{FloralWhite}, - noteborder=2pt, - noteBorderColor={named}{Olive}, - cautionborder=3pt, - cautionBorderColor={named}{Cyan}, - cautionBgColor={named}{LightCyan}} + TitleColor={named}{DarkGoldenrod}, + % pre_border-width is 5.1.0 alias for verbatimborder + pre_border-width=2pt, + % pre_padding is 5.1.0 alias for verbatimsep + pre_padding=5pt, + % rounded boxes are new at 5.1.0 + pre_border-radius=5pt, + % TeXcolor means syntax must be as for LaTeX \definecolor + pre_background-TeXcolor={named}{OldLace}, + pre_border-TeXcolor={named}{Gold}, + % + % 5.1.0 alias for warningborder + div.warning_border-width=3pt, + div.warning_padding=6pt, + div.warning_padding-right=18pt, + div.warning_padding-bottom=18pt, + div.warning_border-TeXcolor={named}{DarkCyan}, + div.warning_background-TeXcolor={named}{LightCyan}, + div.warning_box-shadow=-12pt -12pt inset, + div.warning_box-shadow-TeXcolor={named}{Cyan}, + % + % 5.1.0 new name would be div.attention_border-width + attentionborder=3pt, + % same as div.attention_border-TeXcolor + attentionBorderColor={named}{Crimson}, + % same as div.attention_background-TeXcolor + attentionBgColor={named}{FloralWhite}, + % + % no CSS-like names yet at 5.1.0 for note-type admonitions + noteborder=2pt, + noteBorderColor={named}{Olive}, + hintBorderColor={named}{LightCoral}% + } + And this is placed at the end of the chapter source to end the scope of the configuration:: @@ -852,32 +873,6 @@ 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. @@ -894,20 +889,6 @@ Do not use quotes to enclose values, whether numerical or strings. Default: ``\fboxrule`` -``shadowBorderColor`` - The color of the frame around :dudir:`topic` boxes. - - Default: ``{rgb}{0,0,0}`` (black) - - .. versionadded:: 5.1.0 - -``shadowShadowColor`` - The color of the lateral "shadow" to the right and bottom. - - Default: ``{rgb}{0,0,0}`` (black) - - .. versionadded:: 5.1.0 - |notebdcolors| The colour for the two horizontal rules used by Sphinx in LaTeX for styling a :dudir:`note` type admonition. @@ -981,6 +962,236 @@ Do not use quotes to enclose values, whether numerical or strings. ``attentionborder``, ``dangerborder``, ``errorborder`` +.. _additionalcss: + +Additional CSS-like ``'sphinxsetup'`` keys +------------------------------------------- + +.. versionadded:: 5.1.0 + + +At ``5.1.0`` the LaTeX styling possibilities have been significantly enhanced. +Code-blocks, topic directives, and the five warning-type directives each now +possess: + +- four border-widths parameters, +- four padding parameters, +- four radius parameters (only circular arcs) for the corners, +- optional shadow, with x-offset and y-offset being possibly negative, + and the shadow possibly inset, +- colors for background, border and shadow. + +All those options have been named in a CSS-like way. Indeed, in future it is +envisioned to allow these settings to be specified either in an external file, +or in a string variable which would be parsed to extract from CSS the +selectors and properties which are understood. + +Currently though this is added via a bunch of new ``'sphinxsetup'`` keys +whose names will be given now. + +.. important:: Low-level LaTeX errors causing a build failure can happen if + the input syntax is not respected. In particular properties for colours, + whose names end with ``TeXcolor``, must be input as for the other colour + related options previously described, i.e. for example:: + + ... + div.warning_border-TeXcolor={rgb}{1,0,0},% + ... + + A colon will not be accepted in place of the equal sign which is + expected by the LaTeX syntax. + Do not insert spaces in the input. With the exception of the + ``box-shadow`` all dimensional parameters expect a unique dimension + not a space separated list of dimensions. + +Options for code-blocks: + +- | ``pre_border-top-width``, + | ``pre_border-right-width``, + | ``pre_border-bottom-width``, + | ``pre_border-left-width``, + | ``pre_border-width``, beware that this is a *single* dimension. Its + default, and the ones of the separate widths is the setting of + ``\fboxrule`` in the preamble, i.e. normally ``0.4pt``. +- ``pre_box-decoration-break`` can be set to ``clone`` or ``slice``, default + is ``clone`` for backwards compatibility. +- | ``pre_padding-top``, + | ``pre_padding-right``, + | ``pre_padding-bottom``, + | ``pre_padding-left``, + | ``pre_padding``, again this is a single dimension. Its default is the + setting of ``\fboxsep`` i.e. normally ``3pt``. +- | ``pre_border-top-left-radius``, + | ``pre_border-top-right-radius``, + | ``pre_border-bottom-right-radius``, + | ``pre_border-bottom-left-radius``, + | ``pre_border-radius``, are all single dimensions (rounded corners are + circular arcs only), which default to ``0pt``. +- ``pre_box-shadow`` is special in so far as it may be the ``none`` keyword, + or a single dimension + which will be assigned to both x-offset and y-offset, or two dimensions, or + two dimensions followed by the word ``inset``. The x-offset and y-offset + may be negative. The defaults is ``none``. +- | ``pre_border-TeXcolor``, + | ``pre_background-TeXcolor``, + | ``pre_box-shadow-TeXcolor``. + + They must all be of the format as accepted by LaTeX ``\definecolor``. They + default to ``{rgb}{0,0,0}``, ``{rgb}{1,1,1}`` and ``{rgb}{0,0,0}`` + respectively. + +If one of the radius parameters is positive, the separate border widths will +be ignored and only the value set by ``pre_border-width`` will be used. Also, +if a shadow is present and is inset, the box will be rendered with straight +corners. + +.. note:: + + Rounded boxes are done using the pict2e_ interface to some basic PDF + graphics operations. If this LaTeX package can not be found the build will + proceed and render all boxes with straight corners. + +.. _pict2e: https://ctan.org/pkg/pict2e + + +Options for topic boxes: + +- | ``div.topic_border-top-width``, + | ``div.topic_border-right-width``, + | ``div.topic_border-bottom-width``, + | ``div.topic_border-left-width``, + | ``div.topic_border-width``, beware that this is a *single* dimension. Its + default, and the ones of the separate widths is the setting of + ``\fboxrule`` in the preamble, i.e. normally ``0.4pt``. +- ``div.topic_box-decoration-break`` is currently ignored. +- | ``div.topic_padding-top``, + | ``div.topic_padding-right``, + | ``div.topic_padding-bottom``, + | ``div.topic_padding-left``, + | ``div.topic_padding``, + again this is a single dimension. Its default is ``5pt``. +- | ``div.topic_border-top-left-radius``, + | ``div.topic_border-top-right-radius``, + | ``div.topic_border-bottom-right-radius``, + | ``div.topic_border-bottom-left-radius``, + | ``div.topic_border-radius``. + + They all are single dimensions which default to ``0pt``. +- ``div.topic_box-shadow`` defaults to ``4pt 4pt``. +- | ``div.topic_border-TeXcolor``, + | ``div.topic_background-TeXcolor``, + | ``div.topic_box-shadow-TeXcolor``. + + They must all be of the format as accepted by + LaTeX ``\definecolor``. They default to ``{rgb}{0,0,0}``, ``{rgb}{1,1,1}`` + and ``{rgb}{0,0,0}`` respectively. + +Options for ``warning`` (and similarly for ``caution``, ``attention``, +``danger``, ``error``) directive: + +- | ``div.warning_border-top-width``, + | ``div.warning_border-right-width``, + | ``div.warning_border-bottom-width``, + | ``div.warning_border-left-width``, + | ``div.warning_border-width``, + beware that this is a *single* dimension. Its + default, and the ones of the separate widths is ``1pt``. +- ``div.warning_box-decoration-break`` is currently ignored. +- | ``div.warning_padding-top``, + | ``div.warning_padding-right``, + | ``div.warning_padding-bottom``, + | ``div.warning_padding-left``, + | ``div.warning_padding``, again this is a single dimension. + + .. important:: Prior to ``5.1.0`` there was no separate customizability of + padding for warning-type boxes in PDF via LaTeX output. The sum of + padding and border-width (as set by ``warningborder``, now also named + ``div.warning_border-width``) was kept to a certain constant value (and + this limited the border-width to small values else the border could + overlap the text contents). This behaviour is kept as default. Using + the ``div.warning_padding`` key will cancel for all four paddings the + legacy behaviour, but using only one of the four padding keys leaves the + three other paddings behave as formerly. +- | ``div.warning_border-top-left-radius``, + | ``div.warning_border-top-right-radius``, + | ``div.warning_border-bottom-right-radius``, + | ``div.warning_border-bottom-left-radius``, + | ``div.warning_border-radius``. + + They are all single dimensions which default to ``0pt``. +- ``div.warning_box-shadow`` defaults to ``none``. +- | ``div.warning_border-TeXcolor``, + | ``div.warning_background-TeXcolor``, + | ``div.warning_box-shadow-TeXcolor``. + + They must all be of the format as accepted by + LaTeX ``\definecolor``. They default to ``{rgb}{0,0,0}``, ``{rgb}{1,1,1}`` + and ``{rgb}{0,0,0}`` respectively. + +In the above replace ``warning`` by one of ``caution``, ``attention``, +``danger``, ``error`` to style the respective directives. + +The following legacy behaviour of the PDF layout is currently not +customizable: + +- for code-blocks, padding and border-width and shadow (if one adds one) will + go into the margin; the code lines remain at the same place independently of + the values of the padding and border-width, except for being shifted + vertically of course to not overwrite other text. + +- for topic boxes and warning-type notices only the shadows will go into page + margin, the borders are kept within the text area. + +- ``contents`` and ``topic`` directive are styled the same way. + +.. note:: + + The ``note``-style admonition directives admit no such customization + interface at this stage. + +Here is a random example (not especially recommended!): + +.. code-block:: + + latex_elements = { + 'sphinxsetup': """% + pre_background-TeXcolor={RGB}{242,242,242},% alias of VerbatimColor + pre_border-TeXcolor={RGB}{32,32,32},% + pre_box-decoration-break=slice, + % pre_border-top-width=5pt,% will be ignored due to non-zero radii + % pre_border-right-width=10pt, + % pre_border-bottom-width=15pt, + % pre_border-left-width=20pt, + pre_border-width=3pt,% sets equally the four border-widths, + % needed for rounded corners + pre_border-top-left-radius=20pt, + pre_border-top-right-radius=0pt, + pre_border-bottom-right-radius=20pt, + pre_border-bottom-left-radius=0pt, + pre_box-shadow=10pt 10pt, + pre_box-shadow-TeXcolor={RGB}{192,192,192}, + % + div.topic_border-TeXcolor={RGB}{102,102,102},% + div.topic_box-shadow-TeXcolor={RGB}{187,187,187},% + div.topic_background-TeXcolor={RGB}{238,238,255},% + div.topic_border-bottom-right-radius=10pt,% + div.topic_border-top-right-radius=10pt,% + div.topic_border-width=2pt,% + div.topic_box-shadow=10pt 10pt,% + % + div.danger_border-width=10pt,% + div.danger_padding=6pt,% (see Important notice above) + div.danger_background-TeXcolor={rgb}{0.6,.8,0.8},% + div.danger_border-TeXcolor={RGB}{64,64,64},% + div.danger_box-shadow=-7pt 7pt,% + div.danger_box-shadow-TeXcolor={RGB}{192,192,192},% + div.danger_border-bottom-left-radius=15pt% + """, + } + +In future, it is hoped to add further CSS properties such as ``font`` or +``color``. + LaTeX macros and environments ----------------------------- diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 9b0b54c562..b1105515ba 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -47,6 +47,11 @@ }{ \RequirePackage{color} } +% the \colorlet of xcolor (if at all loaded) is overkill for our use case +\newcommand{\sphinxcolorlet}[2] + {\expandafter\let\csname\@backslashchar color@#1\expandafter\endcsname + \csname\@backslashchar color@#2\endcsname } + % Handle options via "kvoptions" (later loaded by hyperref anyhow) \RequirePackage{kvoptions} @@ -72,36 +77,19 @@ \AtBeginDocument{\define@key{sphinx}{bookmarksdepth}{\hypersetup{bookmarksdepth=#1}}} % \DeclareBoolOption[false]{usespart}% not used % dimensions, we declare the \dimen registers here. -\newdimen\sphinxverbatimsep +\newdimen\sphinxverbatimsep % <-- TO BE REMOVED NOT USED ANYMORE AT 5.1.0 \newdimen\sphinxverbatimborder -\newdimen\sphinxverbatimradius -\newdimen\sphinxshadowsep -\newdimen\sphinxshadowsize -\newdimen\sphinxshadowrule +% % \DeclareStringOption is not convenient for the handling of these dimensions % because we want to assign the values to the corresponding registers. Even if % we added the code to the key handler it would be too late for the initial % set-up and we would need to do initial assignments explicitly. We end up % using \define@key directly. % verbatim -\sphinxverbatimsep=\fboxsep +\sphinxverbatimsep=\fboxsep % <-- TO BE REMOVED NOT USED ANYMORE AT 5.1.0 \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} -\sphinxshadowsize=4pt - \define@key{sphinx}{shadowsize}{\sphinxshadowsize\dimexpr #1\relax} -\sphinxshadowrule=\fboxrule - \define@key{sphinx}{shadowrule}{\sphinxshadowrule\dimexpr #1\relax} -% verbatim \DeclareBoolOption[true]{verbatimwithframe} \DeclareBoolOption[true]{verbatimwrapslines} \DeclareBoolOption[false]{verbatimforcewraps} @@ -119,6 +107,17 @@ \DeclareStringOption % must use braces to hide the brackets [{\makebox[2\fontcharwd\font`\x][r]{\textcolor{red}{\tiny$\m@th\hookrightarrow$}}}]% {verbatimcontinued} +% topic boxes +% alternative names and definitions in 5.1.0 section below +\newdimen\sphinxshadowsep % <-- TO BE REMOVED NOT USED ANYMORE AT 5.1.0 +\newdimen\sphinxshadowsize % <-- TO BE REMOVED NOT USED ANYMORE AT 5.1.0 +\newdimen\sphinxshadowrule +\sphinxshadowsep=5pt + \define@key{sphinx}{shadowsep}{\sphinxshadowsep\dimexpr #1\relax}% +\sphinxshadowsize=4pt + \define@key{sphinx}{shadowsize}{\sphinxshadowsize\dimexpr #1\relax} +\sphinxshadowrule=\fboxrule % catches current value (probably 0.4pt) + \define@key{sphinx}{shadowrule}{\sphinxshadowrule\dimexpr #1\relax} % notices/admonitions % the dimensions for notices/admonitions are kept as macros and assigned to % \spx@notice@border at time of use, hence \DeclareStringOption is ok for this @@ -161,9 +160,6 @@ }% % Default color chosen to be as in minted.sty LaTeX package! \sphinxDeclareSphinxColorOption{VerbatimHighlightColor}{{rgb}{0.878,1,1}} -% topic and contents boxes -\sphinxDeclareSphinxColorOption{shadowBorderColor}{{rgb}{0,0,0}} -\sphinxDeclareSphinxColorOption{shadowShadowColor}{{rgb}{0,0,0}} % admonition boxes, "light" style \sphinxDeclareSphinxColorOption{noteBorderColor}{{rgb}{0,0,0}} \sphinxDeclareSphinxColorOption{hintBorderColor}{{rgb}{0,0,0}} @@ -180,6 +176,416 @@ \sphinxDeclareSphinxColorOption{attentionBgColor}{{rgb}{1,1,1}} \sphinxDeclareSphinxColorOption{dangerBgColor}{{rgb}{1,1,1}} \sphinxDeclareSphinxColorOption{errorBgColor}{{rgb}{1,1,1}} +%%%%%%%% +% +% Additions at 5.1.0 +% +% In future, an alternative user interface will perhaps be provided via +% CSS-like input in a configuration variable latex_css, and Sphinx +% will then parse it into the \sphinxsetup options described it. +% +% In the meantime we adopt already some CSS-like names. However, +% attention to not use these options as genuine CSS properties, only +% very limited syntax is supported. +% +\def\spxstring@none{none} +\def\spxstring@clone{clone} +% Future: should below all the macros holding dimensions be defined via some +% \edef and \dimexpr rather? +% +% Deliberately the code avoids creating (except by \let) new \dimen variables +% besides the legacy ones already defined. +% +% code-blocks +\let\spxdimen@pre@border\sphinxverbatimborder +\define@key{sphinx}{pre_border-top-width}{\def\spx@pre@border@top{#1}} +\define@key{sphinx}{pre_border-right-width}{\def\spx@pre@border@right{#1}} +\define@key{sphinx}{pre_border-bottom-width}{\def\spx@pre@border@bottom{#1}} +\define@key{sphinx}{pre_border-left-width}{\def\spx@pre@border@left{#1}} +% currently accepts only one dimension specification +\define@key{sphinx}{pre_border-width}{% + \spxdimen@pre@border\dimexpr #1\relax + \def\spx@pre@border@top {\spxdimen@pre@border}% + \let\spx@pre@border@right \spx@pre@border@top + \let\spx@pre@border@bottom\spx@pre@border@top + \let\spx@pre@border@left \spx@pre@border@top +} +\def\spx@pre@border@top {\spxdimen@pre@border}% +\let\spx@pre@border@right \spx@pre@border@top +\let\spx@pre@border@bottom\spx@pre@border@top +\let\spx@pre@border@left \spx@pre@border@top +\expandafter\let\expandafter\KV@sphinx@verbatimborder + \csname KV@sphinx@pre_border-width\endcsname +\newif\ifspx@pre@border@open % defaults to false (at least for 5.x series) +\define@key{sphinx}{pre_box-decoration-break}% + {\begingroup\edef\spx@tempa{#1}\expandafter\endgroup + \ifx\spx@tempa\spxstring@clone + \spx@pre@border@openfalse + \else\spx@pre@border@opentrue\fi} +% +% MEMO: \sphinxverbatimsep not used anywhere anymore in the code, to be removed +\define@key{sphinx}{pre_padding-top}{\def\spx@pre@padding@top{#1}} +\define@key{sphinx}{pre_padding-right}{\def\spx@pre@padding@right{#1}} +\define@key{sphinx}{pre_padding-bottom}{\def\spx@pre@padding@bottom{#1}} +\define@key{sphinx}{pre_padding-left}{\def\spx@pre@padding@left{#1}} +\define@key{sphinx}{pre_padding}{% + \def\spx@pre@padding@top {#1}% use some pre \dimexpr expansion? + \let\spx@pre@padding@right \spx@pre@padding@top + \let\spx@pre@padding@bottom\spx@pre@padding@top + \let\spx@pre@padding@left \spx@pre@padding@top +} +\edef\spx@pre@padding@top {\number\fboxsep sp}% \sphinxverbatimsep to be removed +\let\spx@pre@padding@right \spx@pre@padding@top +\let\spx@pre@padding@bottom\spx@pre@padding@top +\let\spx@pre@padding@left \spx@pre@padding@top +\expandafter\let\expandafter\KV@sphinx@verbatimsep + \csname KV@sphinx@pre_padding\endcsname +% +% We do not define a new \dimen (in 5.x pre-5.1.0 dev branch there +% was a \sphinxverbatimradius when rounded boxes were first introduced, +% but we removed it). +\define@key{sphinx}{pre_border-top-left-radius}{\def\spx@pre@radius@topleft{#1}} +\define@key{sphinx}{pre_border-top-right-radius}{\edef\spx@pre@radius@topright{#1}} +\define@key{sphinx}{pre_border-bottom-right-radius}{\def\spx@pre@radius@bottomright{#1}} +\define@key{sphinx}{pre_border-bottom-left-radius}{\def\spx@pre@radius@bottomleft{#1}} +\define@key{sphinx}{pre_border-radius}{% + \def\spx@pre@radius@topleft {#1}% + \let\spx@pre@radius@topright \spx@pre@radius@topleft + \let\spx@pre@radius@bottomright\spx@pre@radius@topleft + \let\spx@pre@radius@bottomleft \spx@pre@radius@topleft +} +% MEMO: keep in mind in using these macros in code elsewhere that they can +% thus be dimen registers or simply dimensional specs such as 3pt +\let\spx@pre@radius@topleft \z@ +\let\spx@pre@radius@topright \z@ +\let\spx@pre@radius@bottomright\z@ +\let\spx@pre@radius@bottomleft \z@ +\AtBeginDocument{\if1\ifdim\spx@pre@radius@topleft>\z@0\fi + \ifdim\spx@pre@radius@topright>\z@0\fi + \ifdim\spx@pre@radius@bottomright>\z@0\fi + \ifdim\spx@pre@radius@bottomleft>\z@0\fi + 1\else\spx@RequirePackage@PictIIe\fi} +% +\newif\ifspx@pre@withshadow +\newif\ifspx@pre@insetshadow +% Attention only "none" or " [optional inset]", no color +\define@key{sphinx}{pre_box-shadow}{\spx@pre@box@shadow@setter #1 {} {} \@nnil}% +% TODO add parsing to fetch color... but this requires a TeX layer to convert +% color spec in CSS format to color/xcolor format +\def\spx@pre@box@shadow@setter #1 #2 #3 #4\@nnil{% + \begingroup\edef\spx@tempa{#1}\expandafter\endgroup + \ifx\spx@tempa\spxstring@none + \spx@pre@withshadowfalse + \else + \spx@pre@withshadowtrue + \edef\spx@pre@shadow@xoffset{\number\dimexpr#1\relax sp}% + \edef\spx@pre@shadow@yoffset{\number\dimexpr#2+\z@\relax sp}% + \if\relax\detokenize{#3}\relax + \spx@pre@insetshadowfalse + \else + \spx@pre@insetshadowtrue + \fi + \fi +}% +\spx@pre@box@shadow@setter none {} {} \@nnil +% +\newif\ifspx@pre@withbordercolor +\define@key{sphinx}{pre_border-TeXcolor}{% + \spx@pre@withbordercolortrue + \definecolor{VerbatimBorderColor}#1% legacy colour name with no sphinx prefix +} +\expandafter\let\expandafter\KV@sphinx@VerbatimBorderColor + \csname KV@sphinx@pre_border-TeXcolor\endcsname +\newif\ifspx@pre@withbackgroundcolor +\define@key{sphinx}{pre_background-TeXcolor}{% + \spx@pre@withbackgroundcolortrue + \definecolor{VerbatimColor}#1% legacy colour name with no sphinx prefix +} +\expandafter\let\expandafter\KV@sphinx@VerbatimColor + \csname KV@sphinx@pre_background-TeXcolor\endcsname +\newif\ifspx@pre@withshadowcolor +\define@key{sphinx}{pre_box-shadow-TeXcolor}{% + \spx@pre@withshadowcolortrue + \definecolor{sphinxVerbatimShadowColor}#1% +} +\definecolor{sphinxVerbatimShadowColor}{rgb}{0,0,0} +% topics +\let\spxdimen@topic@border\sphinxshadowrule +\define@key{sphinx}{div.topic_border-top-width}{\def\spx@topic@border@top{#1}} +\define@key{sphinx}{div.topic_border-right-width}{\def\spx@topic@border@right{#1}} +\define@key{sphinx}{div.topic_border-bottom-width}{\def\spx@topic@border@bottom{#1}} +\define@key{sphinx}{div.topic_border-left-width}{\def\spx@topic@border@left{#1}} +% attention currently accepts only one dimension specification +\define@key{sphinx}{div.topic_border-width}{% + \spxdimen@topic@border\dimexpr #1\relax + \def\spx@topic@border@top {\spxdimen@topic@border}% + \let\spx@topic@border@right \spx@topic@border@top + \let\spx@topic@border@bottom\spx@topic@border@top + \let\spx@topic@border@left \spx@topic@border@top +} +\let\spx@topic@border@top \spxdimen@topic@border +\let\spx@topic@border@right \spx@topic@border@top +\let\spx@topic@border@bottom\spx@topic@border@top +\let\spx@topic@border@left \spx@topic@border@top +\expandafter\let\expandafter\KV@sphinx@shadowrule + \csname KV@sphinx@topic_border-width\endcsname +\newif\ifspx@topic@border@open % defaults to false (legacy) +\define@key{sphinx}{div.topic_box-decoration-break}% + {\begingroup\edef\spx@tempa{#1}\expandafter\endgroup + \ifx\spx@tempa\spxstring@clone + \spx@topic@border@openfalse + \else\spx@topic@border@opentrue\fi}% +% +% MEMO: \sphinxshadowsep not used anywhere anymore in code base and to be removed +\define@key{sphinx}{topic_padding-top}{\def\spx@topic@padding@top{#1}} +\define@key{sphinx}{topic_padding-right}{\def\spx@topic@padding@right{#1}} +\define@key{sphinx}{topic_padding-bottom}{\def\spx@topic@padding@bottom{#1}} +\define@key{sphinx}{topic_padding-left}{\def\spx@topic@padding@left{#1}} +\define@key{sphinx}{topic_padding}{% + \def\spx@topic@padding@top {#1}% + \let\spx@topic@padding@right \spx@topic@padding@top + \let\spx@topic@padding@bottom\spx@topic@padding@top + \let\spx@topic@padding@left \spx@topic@padding@top +} +\def\spx@topic@padding@top {5pt}% no usage anymore of \sphinxshadowsep dimen register +\let\spx@topic@padding@right \spx@topic@padding@top +\let\spx@topic@padding@bottom\spx@topic@padding@top +\let\spx@topic@padding@left \spx@topic@padding@top +\expandafter\let\expandafter\KV@sphinx@shadowsep + \csname KV@sphinx@topic_padding\endcsname +% +\define@key{sphinx}{div.topic_border-top-left-radius}{\def\spx@topic@radius@topleft{#1}} +\define@key{sphinx}{div.topic_border-top-right-radius}{\def\spx@topic@radius@topright{#1}} +\define@key{sphinx}{div.topic_border-bottom-right-radius}{\def\spx@topic@radius@bottomright{#1}} +\define@key{sphinx}{div.topic_border-bottom-left-radius}{\def\spx@topic@radius@bottomleft{#1}} +\define@key{sphinx}{div.topic_border-radius}{% + \def\spx@topic@radius@topleft {#1}% + \let\spx@topic@radius@topright \spx@topic@radius@topleft + \let\spx@topic@radius@bottomright\spx@topic@radius@topleft + \let\spx@topic@radius@bottomleft \spx@topic@radius@topleft +} +\let\spx@topic@radius@topleft \z@ +\let\spx@topic@radius@topright \z@ +\let\spx@topic@radius@bottomright\z@ +\let\spx@topic@radius@bottomleft \z@ +\AtBeginDocument{\if1\ifdim\spx@topic@radius@topleft>\z@0\fi + \ifdim\spx@topic@radius@topright>\z@0\fi + \ifdim\spx@topic@radius@bottomright>\z@0\fi + \ifdim\spx@topic@radius@bottomleft>\z@0\fi + 1\else\spx@RequirePackage@PictIIe\fi} +% +\newif\ifspx@topic@withshadow +\newif\ifspx@topic@insetshadow +% Attention only "none" or " [optional inset]", no color +\define@key{sphinx}{div.topic_box-shadow}{\spx@topic@box@shadow@setter #1 {} {} \@nnil}% +\def\spx@topic@box@shadow@setter #1 #2 #3 #4\@nnil{% + \begingroup\edef\spx@tempa{#1}\expandafter\endgroup + \ifx\spx@tempa\spxstring@none + \spx@topic@withshadowfalse + \else + \spx@topic@withshadowtrue + \edef\spx@topic@shadow@xoffset{\number\dimexpr#1\relax sp}% + \edef\spx@topic@shadow@yoffset{\number\dimexpr#2+\z@\relax sp}% + \if\relax\detokenize{#3}\relax + \spx@topic@insetshadowfalse + \else + \spx@topic@insetshadowtrue + \fi + \fi +}% +\spx@topic@box@shadow@setter 4pt 4pt {} \@nnil +% Suport for legacy shadowsize, the \sphinxshadowsize \dimen register +% is not used anymore and should not even be allocated in future +\define@key{sphinx}{shadowsize}{% + \edef\spx@topic@shadow@xoffset{\number\dimexpr#1\relax sp}% + \let\spx@topic@shadow@yoffset\spx@topic@shadow@xoffset + \ifdim\spx@topic@shadow@xoffset=\z@ + \spx@topic@box@withshadowtrue + \else + \spx@topic@box@withshadowfalse + \spx@topic@box@shadow@insetfalse + \fi +}% +\definecolor{sphinxTopicBorderColor}{rgb}{0,0,0} +\definecolor{sphinxTopicBackgroundColor}{rgb}{1,1,1} +\definecolor{sphinxTopicShadowColor}{rgb}{0,0,0} +\newif\ifspx@topic@withbordercolor +\define@key{sphinx}{div.topic_border-TeXcolor}{% + \spx@topic@withbordercolortrue + \definecolor{sphinxTopicBorderColor}#1% +} +\newif\ifspx@topic@withbackgroundcolor +\define@key{sphinx}{div.topic_background-TeXcolor}{% + \spx@topic@withbackgroundcolortrue + \definecolor{sphinxTopicBackgroundColor}#1% +} +\newif\ifspx@topic@withshadowcolor +\define@key{sphinx}{div.topic_box-shadow-TeXcolor}{% + \spx@topic@withshadowcolortrue + \definecolor{sphinxTopicShadowColor}#1% +} +% warning, caution, attention, danger, error +\def\spx@tempa#1{% + \expandafter\spx@tempb +% MEMO: the diverging naming of first one is conditioned at this time by the fact +% that sphinxnotice environment must work both for these admonitions and the +% note, tip etc... ones + \csname spx@opt@#1border\expandafter\endcsname + \csname spx@#1@border@top\expandafter\endcsname + \csname spx@#1@border@right\expandafter\endcsname + \csname spx@#1@border@bottom\expandafter\endcsname + \csname spx@#1@border@left\expandafter\endcsname + \csname ifspx@#1@border@open\expandafter\endcsname + \csname spx@#1@border@opentrue\expandafter\endcsname + \csname spx@#1@border@openfalse\endcsname + {#1}% +}% +\def\spx@tempb #1#2#3#4#5#6#7#8#9{% + \define@key{sphinx}{div.#9_border-top-width}{\def#2{##1}}% + \define@key{sphinx}{div.#9_border-right-width}{\def#3{##1}}% + \define@key{sphinx}{div.#9_border-bottom-width}{\def#4{##1}}% + \define@key{sphinx}{div.#9_border-left-width}{\def#5{##1}}% + \define@key{sphinx}{div.#9_border-width}{\def#1{##1}\def#2{#1}\let#3#2\let#4#2\let#5#2}% + \def#1{1pt}\let#2#1\let#3#2\let#4#2\let#5#2% + \newif#6% + \define@key{sphinx}{div.#9_box-decoration-break}% + {\begingroup\edef\spx@tempa{##1}\expandafter\endgroup + \ifx\spx@tempa\spxstring@clone#8\else#7\fi}% + \expandafter\let\csname KV@sphinx@#9border\expandafter\endcsname + \csname KV@sphinx@div.#9_border-width\endcsname +} +\spx@tempa{warning} +\spx@tempa{caution} +\spx@tempa{attention} +\spx@tempa{danger} +\spx@tempa{error} + +\def\spx@tempa#1{% + \expandafter\spx@tempb + \csname spx@#1@padding\expandafter\endcsname + \csname spx@#1@padding@top\expandafter\endcsname + \csname spx@#1@padding@right\expandafter\endcsname + \csname spx@#1@padding@bottom\expandafter\endcsname + \csname spx@#1@padding@left\expandafter\endcsname +% MEMO: this is to keep same behaviour as prior to 5.1.0 for which +% no key to set padding adjusted and border+padding was kept constant + \csname spx@opt@#1border\endcsname + {#1}% +}% +\def\spx@tempb #1#2#3#4#5#6#7{% + \define@key{sphinx}{div.#7_padding-top}{\def#2{##1}}% + \define@key{sphinx}{div.#7_padding-right}{\def#3{##1}}% + \define@key{sphinx}{div.#7_padding-bottom}{\def#4{##1}}% + \define@key{sphinx}{div.#7_padding-left}{\def#5{##1}}% + \define@key{sphinx}{div.#7_padding}{\def#1{##1}\def#2{#1}\let#3#2\let#4#2\let#5#2}% +% MEMO: prior to 5.1.0 padding was not separately customizable +% This keeps exactly the strange behaviour as prior to 5.1.0 +% which used to be hard-coded in the sphinxheavybox environment + \def#1{\dimexpr.6\baselineskip-#6\relax}% + \let#2#1\let#3#2\let#4#2\let#5#2% +} +\spx@tempa{warning} +\spx@tempa{caution} +\spx@tempa{attention} +\spx@tempa{danger} +\spx@tempa{error} + +\def\spx@tempa#1{% + \expandafter\spx@tempb + \csname spx@#1@radius@topleft\expandafter\endcsname + \csname spx@#1@radius@topright\expandafter\endcsname + \csname spx@#1@radius@bottomright\expandafter\endcsname + \csname spx@#1@radius@bottomleft\endcsname + {#1}% +}% +\def\spx@tempb #1#2#3#4#5{% + \define@key{sphinx}{div.#5_border-top-left-radius}{\def#1{##1}}% + \define@key{sphinx}{div.#5_border-top-right-radius}{\def#2{##1}}% + \define@key{sphinx}{div.#5_border-bottom-right-radius}{\def#3{##1}}% + \define@key{sphinx}{div.#5_border-bottom-left-radius}{\def#4{##1}}% + \define@key{sphinx}{div.#5_border-radius}{\def#1{##1}\let#2#1\let#3#1\let#4#1}% + \let#1\z@\let#2#1\let#3#2\let#4#2% + \AtBeginDocument{\if1\ifdim#1>\z@0\fi + \ifdim#2>\z@0\fi + \ifdim#3>\z@0\fi + \ifdim#4>\z@0\fi + 1\else\spx@RequirePackage@PictIIe\fi}% +} +\spx@tempa{warning} +\spx@tempa{caution} +\spx@tempa{attention} +\spx@tempa{danger} +\spx@tempa{error} + +\def\spx@tempa#1{% + \expandafter\spx@tempb + \csname ifspx@#1@withshadow\expandafter\endcsname + \csname ifspx@#1@insetshadow\expandafter\endcsname + \csname ifspx@#1@withshadowcolor\expandafter\endcsname + \csname ifspx@#1@withbordercolor\expandafter\endcsname + \csname ifspx@#1@withbackgroundcolor\endcsname +}% +\def\spx@tempb#1#2#3#4#5{\newif#1\newif#2\newif#3\newif#4\newif#5}% +\spx@tempa{warning} +\spx@tempa{caution} +\spx@tempa{attention} +\spx@tempa{danger} +\spx@tempa{error} + +\def\spx@tempa#1{% + \expandafter\spx@tempb + \csname spx@#1@withshadowtrue\expandafter\endcsname + \csname spx@#1@withshadowfalse\expandafter\endcsname + \csname spx@#1@insetshadowtrue\expandafter\endcsname + \csname spx@#1@insetshadowfalse\expandafter\endcsname + \csname spx@#1@box@shadow@setter\expandafter\endcsname + \csname spx@#1@box@shadow@xoffset\expandafter\endcsname + \csname spx@#1@box@shadow@yoffset\endcsname + {#1}% +}% +\def\spx@tempb#1#2#3#4#5#6#7#8{% + \define@key{sphinx}{div.#8_box-shadow}{#5##1 {} {} \@nnil}% + \def#5##1 ##2 ##3 ##4\@nnil{% + \begingroup\edef\spx@tempa{##1}\expandafter\endgroup + \ifx\spx@tempa\spxstring@none + #2% + \else #1\edef#6{\number\dimexpr##1\relax sp}% + \edef#7{\number\dimexpr##2+\z@\relax sp}% + \if\relax\detokenize{##3}\relax#4\else#3\fi + \fi + }#5none {} {} \@nnil +} +\spx@tempa{warning} +\spx@tempa{caution} +\spx@tempa{attention} +\spx@tempa{danger} +\spx@tempa{error} + +\def\spx@tempa#1{% + \expandafter\spx@tempb + \csname spx@#1@withbordercolortrue\expandafter\endcsname + \csname spx@#1@withbackgroundcolortrue\expandafter\endcsname + \csname spx@#1@withshadowcolortrue\endcsname + {#1}% +} +\def\spx@tempb#1#2#3#4{% + \definecolor{sphinx#4BorderColor}{rgb}{0,0,0}% + \definecolor{sphinx#4BgColor}{rgb}{1,1,1}% + \definecolor{sphinx#4ShadowColor}{rgb}{0,0,0}% + \define@key{sphinx}{div.#4_border-TeXcolor}{#1\definecolor{sphinx#4BorderColor}##1}% + \define@key{sphinx}{div.#4_background-TeXcolor}{#2\definecolor{sphinx#4BgColor}##1}% + \define@key{sphinx}{div.#4_box-shadow-TeXcolor}{#3\definecolor{sphinx#4ShadowColor}##1}% + \expandafter\let\csname KV@sphinx@#4BorderColor\expandafter\endcsname + \csname KV@sphinx@div.#4_border-TeXcolor\endcsname + \expandafter\let\csname KV@sphinx@#4BgColor\expandafter\endcsname + \csname KV@sphinx@div.#4_background-TeXcolor\endcsname +} +\spx@tempa{warning} +\spx@tempa{caution} +\spx@tempa{attention} +\spx@tempa{danger} +\spx@tempa{error} + \DeclareDefaultOption{\@unknownoptionerror} \ProcessKeyvalOptions* @@ -278,12 +684,10 @@ %% FRAMED ENVIRONMENTS % +\RequirePackage{sphinxpackageboxes} \input{sphinxlatexadmonitions.sty} \input{sphinxlatexliterals.sty} \input{sphinxlatexshadowbox.sty} -\ifdim\sphinxverbatimradius=\z@\else - \RequirePackage{sphinxpackageboxes} -\fi %% CONTAINERS diff --git a/sphinx/texinputs/sphinxlatexadmonitions.sty b/sphinx/texinputs/sphinxlatexadmonitions.sty index b261ad7f67..052de9bb0b 100644 --- a/sphinx/texinputs/sphinxlatexadmonitions.sty +++ b/sphinx/texinputs/sphinxlatexadmonitions.sty @@ -16,6 +16,7 @@ % settings, cf sphinx docs (latex customization). % % Requires: +\RequirePackage{sphinxpackageboxes} \RequirePackage{framed}% used by sphinxheavybox % % Dependencies (they do not need to be defined at time of loading): @@ -65,24 +66,116 @@ \definecolor{sphinxtipBgColor}{rgb}{1,1,1} % Others get more distinction +\def\spx@admonitions@boxes@fcolorbox@setup{% + \spx@boxes@border@top \@nameuse{spx@\spx@noticetype @border@top}% + \spx@boxes@border@right \@nameuse{spx@\spx@noticetype @border@right}% + \spx@boxes@border@bottom\@nameuse{spx@\spx@noticetype @border@bottom}% + \spx@boxes@border@left \@nameuse{spx@\spx@noticetype @border@left}% + \spx@boxes@border \spx@notice@border +% + \spx@boxes@padding@top \@nameuse{spx@\spx@noticetype @padding@top}% + \spx@boxes@padding@right \@nameuse{spx@\spx@noticetype @padding@right}% + \spx@boxes@padding@bottom\@nameuse{spx@\spx@noticetype @padding@bottom}% + \spx@boxes@padding@left \@nameuse{spx@\spx@noticetype @padding@left}% +% + \spx@boxes@radius@topleft \@nameuse{spx@\spx@noticetype @radius@topleft}% + \spx@boxes@radius@topright \@nameuse{spx@\spx@noticetype @radius@topright}% + \spx@boxes@radius@bottomright \@nameuse{spx@\spx@noticetype @radius@bottomright}% + \spx@boxes@radius@bottomleft \@nameuse{spx@\spx@noticetype @radius@bottomleft}% + \relax + \iftrue\@nameuse{ifspx@\spx@noticetype @withshadow}% + \spx@boxes@withshadowtrue + \spx@boxes@shadow@xoffset \@nameuse{spx@\spx@noticetype @box@shadow@xoffset}% + \spx@boxes@shadow@yoffset \@nameuse{spx@\spx@noticetype @box@shadow@yoffset}\relax + \else + \spx@boxes@withshadowfalse + \fi\@nameuse{fi}% + \iftrue\@nameuse{ifspx@\spx@noticetype @insetshadow}% + \spx@boxes@insetshadowtrue + \else + \spx@boxes@insetshadowfalse + \fi\@nameuse{fi}% + \iftrue\@nameuse{ifspx@\spx@noticetype @withshadowcolor}% + \spx@boxes@withshadowcolortrue + \else + \spx@boxes@withshadowcolorfalse + \fi\@nameuse{fi}% + % + \iftrue\@nameuse{ifspx@\spx@noticetype @withbackgroundcolor}% + \spx@boxes@withbackgroundcolortrue + \else + \spx@boxes@withbackgroundcolorfalse + \fi\@nameuse{fi}% + \sphinxcolorlet{spx@boxes@backgroundcolor}{spx@notice@bgcolor}% + % + \iftrue\@nameuse{ifspx@\spx@noticetype @withbordercolor}% + \spx@boxes@withbordercolortrue + \else + \spx@boxes@withbordercolorfalse + \fi\@nameuse{fi}% + \sphinxcolorlet{spx@boxes@bordercolor}{spx@notice@bordercolor}% + % + \iftrue\@nameuse{ifspx@\spx@noticetype @withshadowcolor}% + \spx@boxes@withshadowcolortrue + \else + \spx@boxes@withshadowcolorfalse + \fi\@nameuse{fi}% + \sphinxcolorlet{spx@boxes@shadowcolor}{sphinx\spx@noticetype ShadowColor}% +} % Code adapted from framed.sty's "snugshade" environment. % Nesting works (inner frames do not allow page breaks). \newenvironment{sphinxheavybox}{\par - \setlength{\FrameRule}{\spx@notice@border}% - \setlength{\FrameSep}{\dimexpr.6\baselineskip-\FrameRule\relax} + \spx@admonitions@boxes@fcolorbox@setup + % Those are used by sphinxVerbatim if the \ifspx@inframed boolean is true + \setlength{\FrameRule}{0.5\dimexpr\spx@boxes@border@top+\spx@boxes@border@bottom\relax}% + % MEMO: prior to 5.1.0 \FrameSep was determined as 0.6\baselineskip - + % \FrameRule, and there was no possibility for user to adjust padding. + % Then \fcolorbox was used with \fboxrule set to \FrameRule and \fboxsep + % set to \FrameSep. + % The 5.1.0 default calculation of padding parameters maintains PDF output + % identical to legacy behaviour, as long as padding is not set by user. + \setlength{\FrameSep}{0.5\dimexpr\spx@boxes@padding@top+\spx@boxes@padding@bottom\relax}% \advance\spx@image@maxheight - -\dimexpr2\FrameRule - +2\FrameSep + -\dimexpr\spx@boxes@border@top+\spx@boxes@border@bottom + +\spx@boxes@padding@top+\spx@boxes@padding@bottom +\baselineskip\relax % will happen again if nested, needed indeed! + % MEMO: the next comment is before boxing was extended to allow padding and + % multiple border-widths, not to mention shadows... % configure framed.sty's parameters to obtain same vertical spacing % as for "light" boxes. We need for this to manually insert parskip glue and % revert a skip done by framed before the frame. \ltx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}% \vspace{\FrameHeightAdjust} % copied/adapted from framed.sty's snugshade + % but now using in place of \fcolorbox the Sphinx sophisticated own \def\FrameCommand##1{\hskip\@totalleftmargin - \fboxsep\FrameSep \fboxrule\FrameRule - \fcolorbox{spx@notice@bordercolor}{spx@notice@bgcolor}{##1}% + \ifspx@boxes@withshadow + \ifspx@boxes@insetshadow\else + \ifdim\spx@boxes@shadow@xoffset<\z@\hskip\spx@boxes@shadow@xoffset\relax + \fi + \fi + \fi + \if1% use rounded boxes only if needed and possible + \ifdim\spx@boxes@radius@topleft >\z@0\fi + \ifdim\spx@boxes@radius@topright >\z@0\fi + \ifdim\spx@boxes@radius@bottomright>\z@0\fi + \ifdim\spx@boxes@radius@bottomleft >\z@0\fi + 1\spx@boxes@fcolorbox{##1}% + \else + \@ifpackageloaded{pict2e}% + {\ifspx@boxes@insetshadow + \spx@boxes@fcolorbox{##1}% + \else + \spx@boxes@fcolorbox@rounded{##1}% + \fi}% + {\spx@boxes@fcolorbox{##1}}% + \fi + \ifspx@boxes@withshadow + \ifspx@boxes@insetshadow\else + \ifdim\spx@boxes@shadow@xoffset>\z@\hskip-\spx@boxes@shadow@xoffset\relax + \fi + \fi + \fi \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}% \savenotes % use a minipage if we are already inside a framed environment @@ -129,11 +222,6 @@ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}} % or just use package options -% the \colorlet of xcolor (if at all loaded) is overkill for our use case -\newcommand{\sphinxcolorlet}[2] - {\expandafter\let\csname\@backslashchar color@#1\expandafter\endcsname - \csname\@backslashchar color@#2\endcsname } - % the main dispatch for all types of notices \newenvironment{sphinxadmonition}[2]{% #1=type, #2=heading % can't use #1 directly in definition of end part diff --git a/sphinx/texinputs/sphinxlatexliterals.sty b/sphinx/texinputs/sphinxlatexliterals.sty index b4eb391740..35fc9ca9fb 100644 --- a/sphinx/texinputs/sphinxlatexliterals.sty +++ b/sphinx/texinputs/sphinxlatexliterals.sty @@ -32,6 +32,8 @@ % - alltt % - upquote % - needspace +% - sphinxpackageboxes +\RequirePackage{sphinxpackageboxes} % also in sphinxlatexadmonitions.sty: % This is a workaround to a "feature" of French lists, when literal block @@ -60,9 +62,6 @@ % Skip to next page if not enough space at bottom \RequirePackage{needspace} -\newbox\spx@verb@tempboxa -\newbox\spx@verb@tempboxb - % Based on use of "fancyvrb.sty"'s Verbatim. % - with framing allowing page breaks ("framed.sty") % - with breaking of long lines (exploits Pygments mark-up), @@ -109,8 +108,7 @@ % "color push" or "color pop" % About the produced output: % - it obeys current indentation, -% - frame of width \sphinxverbatimborder is \sphinxverbatimsep -arated -% from the contents, +% - frame with 4 padding parameters and 4 border-width parameters % - 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, @@ -119,14 +117,27 @@ % #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 + \ifspx@opt@verbatimwithframe\else\spxdimen@pre@border\z@\fi \hskip\@totalleftmargin - \hskip-\sphinxverbatimsep\hskip-\sphinxverbatimborder + \hskip-\spx@pre@border@left\hskip-\spx@pre@padding@left\relax + \ifspx@pre@withshadow + \ifspx@pre@insetshadow\else + \ifdim\spx@pre@shadow@xoffset<\z@\hskip\spx@pre@shadow@xoffset\relax + \fi + \fi + \fi \spx@verb@fcolorbox {#1}{#2}{#3}% - \hskip-\sphinxverbatimsep\hskip-\sphinxverbatimborder + \hskip-\spx@pre@padding@right\hskip-\spx@pre@border@right\relax + \ifspx@pre@withshadow + \ifspx@pre@insetshadow\else + \ifdim\spx@pre@shadow@xoffset>\z@\hskip-\spx@pre@shadow@xoffset\relax + \fi + \fi + \fi \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth }% \long\def\spx@verb@fcolorbox #1#2#3{% @@ -138,82 +149,148 @@ % 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" - % 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 + \setbox\z@\hbox{#3}% + \edef\spx@verb@fcolorbox@width@sp + {\number\dimexpr\wd\z@+\spx@pre@border@left + +\spx@pre@padding@left + +\spx@pre@padding@right + +\spx@pre@border@right\relax sp}% + \vbox{#1% continuation hint attached above frame, uses \spx@verb@fcolorbox@width@sp + % the boxes@fcolorbox constructs an \hbox with bbox containing the border + \if1% use rounded boxes only if needed and possible + \ifdim\spx@pre@radius@topleft >\z@0\fi + \ifdim\spx@pre@radius@topright >\z@0\fi + \ifdim\spx@pre@radius@bottomright>\z@0\fi + \ifdim\spx@pre@radius@bottomleft >\z@0\fi + 1\spx@boxes@fcolorbox{\box\z@}% + \else + \@ifpackageloaded{pict2e}% + {\ifspx@pre@insetshadow + \spx@boxes@fcolorbox{\box\z@}% + \else + \spx@boxes@fcolorbox@rounded{\box\z@}% + \fi}% + {\spx@boxes@fcolorbox{\box\z@}}% + \fi + % This \nointerlineskip to maintain legacy spacing when a \hrule was + % formerly last prior item in vertical list. TODO: remove this at 6.0.0 ? \nointerlineskip - % TODO: add some \lineskip glue here, this is all in a \vbox so can't split - #2% continuation hint attached below frame + #2% continuation hint attached below frame, uses \spx@verb@fcolorbox@width@sp }% end of \vbox }% -\def\spx@fcolorbox@put@c#1{% hide width from framed.sty measuring - \moveright.5\wd\tw@\hb@xt@\z@{\hss#1\hss}% +\def\spx@verb@fcolorbox@put@c#1{% hide width from framed.sty measuring + \moveright.5\dimexpr\spx@verb@fcolorbox@width@sp\hb@xt@\z@{\hss#1\hss}% }% -\def\spx@fcolorbox@put@r#1{% right align with contents, width hidden - \moveright\dimexpr\wd\tw@-\sphinxverbatimsep-\sphinxverbatimborder\hb@xt@\z@{\hss#1}% +\def\spx@verb@fcolorbox@put@r#1{% right align with contents, width hidden + \moveright\dimexpr\spx@verb@fcolorbox@width@sp-% + \spx@pre@padding@right-% + \spx@pre@border@right\hb@xt@\z@{\hss#1}% }% -\def\spx@fcolorbox@put@l#1{% left align with contents, width hidden - \moveright\dimexpr\sphinxverbatimborder+\sphinxverbatimsep\hb@xt@\z@{#1\hss}% +\def\spx@verb@fcolorbox@put@l#1{% left align with contents, width hidden + \moveright\dimexpr\spx@pre@border@left+% + \spx@pre@padding@left\hb@xt@\z@{#1\hss}% }% % -\def\sphinxVerbatim@Continued - {\csname spx@fcolorbox@put@\spx@opt@verbatimcontinuedalign\endcsname - {{\normalcolor\sphinxstylecodecontinued\literalblockcontinuedname}}}% -\def\sphinxVerbatim@Continues - {\csname spx@fcolorbox@put@\spx@opt@verbatimcontinuesalign\endcsname - {{\normalcolor\sphinxstylecodecontinues\literalblockcontinuesname}}}% -\def\sphinxVerbatim@Title - {\spx@fcolorbox@put@c{\unhcopy\sphinxVerbatim@TitleBox}}% +\def\sphinxVerbatim@Continued{% + \csname spx@verb@fcolorbox@put@\spx@opt@verbatimcontinuedalign\endcsname + {{\normalcolor\sphinxstylecodecontinued\literalblockcontinuedname}}% +}% +\def\sphinxVerbatim@Continues{% + \csname spx@verb@fcolorbox@put@\spx@opt@verbatimcontinuesalign\endcsname + {{\normalcolor\sphinxstylecodecontinues\literalblockcontinuesname}}% +}% +\def\sphinxVerbatim@Title{% + \spx@verb@fcolorbox@put@c{\unhcopy\sphinxVerbatim@TitleBox}% +}% \let\sphinxVerbatim@Before\@empty \let\sphinxVerbatim@After\@empty % Defaults are redefined in document preamble according to language \newcommand*\literalblockcontinuedname{continued from previous page}% \newcommand*\literalblockcontinuesname{continues on next page}% % -\def\sphinxVerbatim@FrameCommand - {\spx@verb@FrameCommand\sphinxVerbatim@Before\sphinxVerbatim@After}% -\def\sphinxVerbatim@FirstFrameCommand - {\spx@verb@FrameCommand\sphinxVerbatim@Before\sphinxVerbatim@Continues}% -\def\sphinxVerbatim@MidFrameCommand - {\spx@verb@FrameCommand\sphinxVerbatim@Continued\sphinxVerbatim@Continues}% -\def\sphinxVerbatim@LastFrameCommand - {\spx@verb@FrameCommand\sphinxVerbatim@Continued\sphinxVerbatim@After}% +\def\sphinxVerbatim@FrameCommand{% + \spx@verb@FrameCommand\sphinxVerbatim@Before\sphinxVerbatim@After +}% +\def\sphinxVerbatim@FirstFrameCommand{% + \ifspx@pre@border@open + \let\spx@boxes@fcolorbox@setuphook\spx@verb@boxes@fcolorbox@setuphook@openbottom + \fi + \spx@verb@FrameCommand\sphinxVerbatim@Before\sphinxVerbatim@Continues +}% +\def\sphinxVerbatim@MidFrameCommand{% + \ifspx@pre@border@open + \let\spx@boxes@fcolorbox@setuphook\spx@verb@boxes@fcolorbox@setuphook@openboth + \fi + \spx@verb@FrameCommand\sphinxVerbatim@Continued\sphinxVerbatim@Continues +}% +\def\sphinxVerbatim@LastFrameCommand{% + \ifspx@pre@border@open + \let\spx@boxes@fcolorbox@setuphook\spx@verb@boxes@fcolorbox@setuphook@opentop + \fi + \spx@verb@FrameCommand\sphinxVerbatim@Continued\sphinxVerbatim@After +}% +% +\def\spx@verb@boxes@fcolorbox@setup{% +% + \spx@boxes@border@top \spx@pre@border@top + \spx@boxes@border@right \spx@pre@border@right + \spx@boxes@border@bottom\spx@pre@border@bottom + \spx@boxes@border@left \spx@pre@border@left + \spx@boxes@border \spxdimen@pre@border +% + \spx@boxes@padding@top \spx@pre@padding@top + \spx@boxes@padding@right \spx@pre@padding@right + \spx@boxes@padding@bottom\spx@pre@padding@bottom + \spx@boxes@padding@left \spx@pre@padding@left +% + \spx@boxes@radius@topleft \spx@pre@radius@topleft + \spx@boxes@radius@topright \spx@pre@radius@topright + \spx@boxes@radius@bottomright \spx@pre@radius@bottomright + \spx@boxes@radius@bottomleft \spx@pre@radius@bottomleft +% +% + \ifspx@pre@withshadow + \spx@boxes@withshadowtrue + \spx@boxes@shadow@xoffset \spx@pre@shadow@xoffset + \spx@boxes@shadow@yoffset \spx@pre@shadow@yoffset\relax + \else + \spx@boxes@withshadowfalse + \fi + \ifspx@pre@insetshadow\spx@boxes@insetshadowtrue\else + \spx@boxes@insetshadowfalse\fi + \ifspx@pre@withshadowcolor\spx@boxes@withshadowcolortrue\else + \spx@boxes@withshadowcolorfalse\fi + % + \ifspx@pre@withbackgroundcolor\spx@boxes@withbackgroundcolortrue\else + \spx@boxes@withbackgroundcolorfalse\fi + \sphinxcolorlet{spx@boxes@backgroundcolor}{VerbatimColor}% + % + \ifspx@pre@withbordercolor\spx@boxes@withbordercolortrue\else + \spx@boxes@withbordercolorfalse\fi + \sphinxcolorlet{spx@boxes@bordercolor}{VerbatimBorderColor}% + % + \ifspx@pre@withshadowcolor\spx@boxes@withshadowcolortrue\else + \spx@boxes@withshadowcolorfalse\fi + \sphinxcolorlet{spx@boxes@shadowcolor}{sphinxVerbatimShadowColor}% +}% +\def\spx@verb@boxes@fcolorbox@setuphook@openbottom{% + \spx@boxes@border@bottom \z@ + \spx@boxes@radius@bottomright\z@ + \spx@boxes@radius@bottomleft \z@ +}% +\def\spx@verb@boxes@fcolorbox@setuphook@opentop{% + \spx@boxes@border@top \z@ + \spx@boxes@radius@topright\z@ + \spx@boxes@radius@topleft \z@ +}% +\def\spx@verb@boxes@fcolorbox@setuphook@openboth{% + \spx@boxes@border@top \z@ + \spx@boxes@border@bottom \z@ + \spx@boxes@radius@topright\z@ + \spx@boxes@radius@topleft \z@ + \spx@boxes@radius@bottomright\z@ + \spx@boxes@radius@bottomleft \z@ +}% % For linebreaks inside Verbatim environment from package fancyvrb. \newbox\sphinxcontinuationbox @@ -348,7 +425,7 @@ % \newcommand\sphinxVerbatimFormatLine[1]{\FV@ObeyTabs{\strut #1}}% \newcommand\sphinxVerbatimFormatLine[1]{\strut#1}% % MEMO: if verbatimwrapslines is set to true (default) the #1 above is -% simply \box\spx@verb@tempboxb, from the next two macros. +% simply \box\spx@tempboxb, from the next two macros. % The next two macros are a deep hack of fancyvrb.sty core line processing in % order to wrap too long lines, either at spaces and natural break-points, % (soft wrap) or optionally at any character (hard wrap). This requires deep @@ -367,10 +444,10 @@ \def\spx@verb@@ProcessLines{% \unskip \unpenalty - \setbox\spx@verb@tempboxb\lastbox -\ifvoid\spx@verb@tempboxb\else + \setbox\spx@tempboxb\lastbox +\ifvoid\spx@tempboxb\else {\spx@verb@@ProcessLines}% - \FV@ProcessLine{\box\spx@verb@tempboxb}% + \FV@ProcessLine{\box\spx@tempboxb}% \global\let\FV@ProcessLine\FV@ProcessLine \global\setbox\@tempboxa=\box\@tempboxa \aftergroup\spx@verb@@InhibitLineNumber @@ -401,7 +478,7 @@ \fi % MEMO: \everypar{} was issued earlier (and due to \@setminipage % would have been only \@minipagefalse\everypar{} otherwise). - \setbox\spx@verb@tempboxa=\vtop{\hsize\linewidth + \setbox\spx@tempboxa=\vtop{\hsize\linewidth \raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ \doublehyphendemerits\z@\finalhyphendemerits\z@ % MEMO: fancyvrb has options obeytabs and tabsize. Anyhow tab characters @@ -417,14 +494,14 @@ % are executed but not the ones at its end. \par }% - \setbox\spx@verb@tempboxa=\vtop{\unvbox\spx@verb@tempboxa - \setbox\spx@verb@tempboxb\lastbox + \setbox\spx@tempboxa=\vtop{\unvbox\spx@tempboxa + \setbox\spx@tempboxb\lastbox {\spx@verb@@ProcessLines}% - \FV@ProcessLine{\box\spx@verb@tempboxb}% + \FV@ProcessLine{\box\spx@tempboxb}% \global\let\FV@ProcessLine\FV@ProcessLine \global\setbox\@tempboxa=\box\@tempboxa }% - \unvbox\spx@verb@tempboxa + \unvbox\spx@tempboxa }% % % The normal line wrapping allows breaks at spaces and ascii non @@ -493,7 +570,7 @@ \long\def\spx@verb@DecideIfWillDoForceWrap{% \global\let\spx@verb@maxwidth\z@ \global\let\spx@verb@minwidth\linewidth - \setbox\spx@verb@tempboxa + \setbox\spx@tempboxa \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ \doublehyphendemerits\z@\finalhyphendemerits\z@ \spx@everypar{}\noindent\strut\FV@Line\strut\spx@par @@ -514,27 +591,27 @@ % but minwidth must not take into account the last line \def\spx@verb@getwidths {% \unskip\unpenalty - \setbox\spx@verb@tempboxb\lastbox - \ifvoid\spx@verb@tempboxb + \setbox\spx@tempboxb\lastbox + \ifvoid\spx@tempboxb \else - \setbox\spx@verb@tempboxb\hbox{\unhbox\spx@verb@tempboxb}% - \ifdim\spx@verb@maxwidth<\wd\spx@verb@tempboxb - \xdef\spx@verb@maxwidth{\number\wd\spx@verb@tempboxb sp}% + \setbox\spx@tempboxb\hbox{\unhbox\spx@tempboxb}% + \ifdim\spx@verb@maxwidth<\wd\spx@tempboxb + \xdef\spx@verb@maxwidth{\number\wd\spx@tempboxb sp}% \fi \expandafter\spx@verb@getwidths@loop \fi }% \def\spx@verb@getwidths@loop {% \unskip\unpenalty - \setbox\spx@verb@tempboxb\lastbox - \ifvoid\spx@verb@tempboxb + \setbox\spx@tempboxb\lastbox + \ifvoid\spx@tempboxb \else - \setbox\spx@verb@tempboxb\hbox{\unhbox\spx@verb@tempboxb}% - \ifdim\spx@verb@maxwidth<\wd\spx@verb@tempboxb - \xdef\spx@verb@maxwidth{\number\wd\spx@verb@tempboxb sp}% + \setbox\spx@tempboxb\hbox{\unhbox\spx@tempboxb}% + \ifdim\spx@verb@maxwidth<\wd\spx@tempboxb + \xdef\spx@verb@maxwidth{\number\wd\spx@tempboxb sp}% \fi - \ifdim\spx@verb@minwidth>\wd\spx@verb@tempboxb - \xdef\spx@verb@minwidth{\number\wd\spx@verb@tempboxb sp}% + \ifdim\spx@verb@minwidth>\wd\spx@tempboxb + \xdef\spx@verb@minwidth{\number\wd\spx@tempboxb sp}% \fi \expandafter\spx@verb@getwidths@loop \fi @@ -656,14 +733,20 @@ \kern\dimexpr-\dp\strutbox+\sphinxbelowcaptionspace % if no frame (code-blocks inside table cells), remove % the "verbatimsep" whitespace from the top (better visually) - \ifspx@opt@verbatimwithframe\else-\sphinxverbatimsep\fi + \ifspx@opt@verbatimwithframe\else + % but we must now check if there is a background color + \ifspx@pre@withbackgroundcolor\else-\spx@pre@padding@top\fi + \fi % caption package adds \abovecaptionskip vspace, remove it \spx@ifcaptionpackage{-\abovecaptionskip}{}\relax}% \else \vskip\sphinxverbatimsmallskipamount \def\sphinxVerbatim@After {\nointerlineskip\kern\dimexpr\dp\strutbox - \ifspx@opt@verbatimwithframe\else-\sphinxverbatimsep\fi + \ifspx@opt@verbatimwithframe\else + % but we must now check if there is a background color + \ifspx@pre@withbackgroundcolor\else-\spx@pre@padding@bottom\fi + \fi \spx@ifcaptionpackage{-\abovecaptionskip}{}\relax \sphinxVerbatim@Title}% \fi @@ -680,14 +763,21 @@ \fi \global\let\sphinxLiteralBlockLabel\empty \global\let\sphinxVerbatimTitle\empty + % the "FrameCommand"'s will check status of verbatimwithframe option + % to decide if to stroke the borders ; ultimately they are also + % responsible to attach the "Title". \let\FrameCommand \sphinxVerbatim@FrameCommand + % those will also check status of the pre_box-decoration-break option \let\FirstFrameCommand\sphinxVerbatim@FirstFrameCommand \let\MidFrameCommand \sphinxVerbatim@MidFrameCommand \let\LastFrameCommand \sphinxVerbatim@LastFrameCommand + % \ifspx@opt@verbatimhintsturnover\else \let\sphinxVerbatim@Continued\@empty \let\sphinxVerbatim@Continues\@empty \fi + % initialization for \spx@boxes@fcolorbox from sphinxpackageboxes.sty + \spx@verb@boxes@fcolorbox@setup \ifspx@opt@verbatimwrapslines % deep hack into fancyvrb's internal processing of input lines \let\FV@@PreProcessLine\spx@verb@@PreProcessLine @@ -748,18 +838,31 @@ \color@begingroup % protect against color leaks (upstream framed.sty bug) % will fetch its optional arguments if any \OriginalVerbatim -} +}% {% \endOriginalVerbatim \color@endgroup % matches the \color@begingroup \ifspx@inframed \egroup % finish \sphinxVerbatim@ContentsBox vbox \nobreak % update page totals - \ifdim\dimexpr\ht\sphinxVerbatim@ContentsBox+ +%%%% +% MEMO (2022/07/09, while preparing 5.1.0 LaTeX CSS-style sphinxsetup options) +% This test will systematically cause to abandon framing if the code-block +% is near bottom of a warning-type notice which TeX has not yet decided whether +% it fits on current page and which is near bottom of page. Indeed the +% \pagetotal will already be very near \pagegoal. This is probably a not +% intended behaviour, and perhaps the whole thing should be removed? Indeed +% the result is surprising then because the notice will be split, code-block +% will be on page 2 and will have no background-color, no border. + \ifdim\dimexpr + \ht\sphinxVerbatim@ContentsBox+ \dp\sphinxVerbatim@ContentsBox+ \ht\sphinxVerbatim@TitleBox+ \dp\sphinxVerbatim@TitleBox+ - 2\sphinxverbatimsep+\ifspx@opt@verbatimwithframe 2\sphinxverbatimborder+\fi + \spx@pre@padding@top+ + \spx@pre@padding@bottom+ + \ifspx@opt@verbatimwithframe \spx@pre@border@top+ + \spx@pre@border@bottom+\fi % try to account for external frame parameters % MEMO: this is because the sphinxheavybox (for warning admonitions) % environment sets \FrameSep and \FrameRule diff --git a/sphinx/texinputs/sphinxlatexshadowbox.sty b/sphinx/texinputs/sphinxlatexshadowbox.sty index 4a013ef65b..d9a35eb56c 100644 --- a/sphinx/texinputs/sphinxlatexshadowbox.sty +++ b/sphinx/texinputs/sphinxlatexshadowbox.sty @@ -16,74 +16,83 @@ % % Requires: \RequirePackage{framed} +\RequirePackage{sphinxpackageboxes} -% Let's draw the contents first, then the frame and the shadow last, -% to avoid problems with some pdf viewers. -\long\def\spx@ShadowFBox#1{% - \leavevmode\begingroup - % First we prepare a box with the contents and some reserved space for the - % frame and inner separation; with more parameters we could allow various - % border widths for top, bottom, left, right, but here all are equal. - \setbox\@tempboxa - \hbox{\kern\sphinxshadowrule - \vbox{\kern\sphinxshadowrule - \kern\sphinxshadowsep - \hbox{\kern\sphinxshadowsep #1\kern\sphinxshadowsep}% - \kern\sphinxshadowsep - \kern\sphinxshadowrule}% - \kern\sphinxshadowrule}% - % Now we rebox, adding the colored frame for which space was reserved. - \setbox\@tempboxa - \hbox{\unhcopy\@tempboxa % not \unhbox to be able to refer to \ht, \wd later - \kern-\wd\@tempboxa - {\color{sphinxshadowBorderColor}% color push here - \vrule\@width\sphinxshadowrule% TeX auto-computes the height - \vbox{\hrule\@height\sphinxshadowrule% TeX auto-computes the width - \kern\dimexpr\ht\@tempboxa-\sphinxshadowrule\relax - % This empty \hbox is here to give width used by \hrule - % As \dp\@tempboxa is zero, the \hbox location is at the - % bottom of frame. - \hbox{\kern\dimexpr\wd\@tempboxa-2\sphinxshadowrule\relax}% - \kern\dimexpr\dp\@tempboxa-\sphinxshadowrule\relax - \hrule\@height\sphinxshadowrule% TeX auto-computes the width - }% - \vrule\@width\sphinxshadowrule% TeX auto-computes the height - }% color pop will happen here - }% - % Now we add the shadow. +\def\spx@shadowbox@boxes@fcolorbox@setup{% +% + \spx@boxes@border@top \spx@topic@border@top + \spx@boxes@border@right \spx@topic@border@right + \spx@boxes@border@bottom\spx@topic@border@bottom + \spx@boxes@border@left \spx@topic@border@left + \spx@boxes@border \spxdimen@topic@border +% + \spx@boxes@padding@top \spx@topic@padding@top + \spx@boxes@padding@right \spx@topic@padding@right + \spx@boxes@padding@bottom\spx@topic@padding@bottom + \spx@boxes@padding@left \spx@topic@padding@left +% + \spx@boxes@radius@topleft \spx@topic@radius@topleft + \spx@boxes@radius@topright \spx@topic@radius@topright + \spx@boxes@radius@bottomright \spx@topic@radius@bottomright + \spx@boxes@radius@bottomleft \spx@topic@radius@bottomleft\relax +% + \ifspx@topic@withshadow + \spx@boxes@withshadowtrue + \spx@boxes@shadow@xoffset \spx@topic@shadow@xoffset + \spx@boxes@shadow@yoffset \spx@topic@shadow@yoffset\relax + \else + \spx@boxes@withshadowfalse + \fi + \ifspx@topic@insetshadow\spx@boxes@insetshadowtrue\else + \spx@boxes@insetshadowfalse\fi + \ifspx@topic@withshadowcolor\spx@boxes@withshadowcolortrue\else + \spx@boxes@withshadowcolorfalse\fi + % + \ifspx@topic@withbackgroundcolor\spx@boxes@withbackgroundcolortrue\else + \spx@boxes@withbackgroundcolorfalse\fi + \sphinxcolorlet{spx@boxes@backgroundcolor}{sphinxTopicBackgroundColor}% % - % Formerly, shadow was drawn partly on top of frame, but this was before - % both frame and shadow acquired colors. The width of the part of the - % shadow on the right is hidden, so it will stick into the right page - % margin. + \ifspx@topic@withbordercolor\spx@boxes@withbordercolortrue\else + \spx@boxes@withbordercolorfalse\fi + \sphinxcolorlet{spx@boxes@bordercolor}{sphinxTopicBorderColor}% % - % The frame borders are included into this final \hbox, which is sent back - % to \MakeFramed/\endMakeFramed measurements and then finally to page - % shipout. As \advance\hsize-\width appears in \MakeFramed, where \width is - % the computed extra width added by the framing plus inner separation (so - % actually 2\sphinxshadowrule+2\sphinxshadowsep), this all means that - % horizontally the frame will be perfectly adjusted to the *total* text - % width limits (i.e. independent of current list nesting; but anyhow - % Docutils does not allow nesting of topic within topics or body elements). - \hbox{\vbox{\offinterlineskip - \hbox{\copy\@tempboxa % not \box as we need \wd and \ht next - % add shadow on right side - \lower\sphinxshadowsize - \hbox{{\color{sphinxshadowShadowColor}% - \vrule\@height\ht\@tempboxa \@width\sphinxshadowsize}}% - }% - \kern-\sphinxshadowsize % shift back vertically to bottom of frame - % and add shadow at bottom - \moveright\sphinxshadowsize - \vbox{{\color{sphinxshadowShadowColor}% - \hrule\@width\wd\@tempboxa \@height\sphinxshadowsize}}% - }% - % move left by the size of right shadow so shadow adds no width, and - % will stick into right margin - % (we did not conceal of course from TeX the depth) - \kern-\sphinxshadowsize - }% - \endgroup + \ifspx@topic@withshadowcolor\spx@boxes@withshadowcolortrue\else + \spx@boxes@withshadowcolorfalse\fi + \sphinxcolorlet{spx@boxes@shadowcolor}{sphinxTopicShadowColor}% +}% + +% At 5.1.0 the code formerly here has been refactored and incorporated +% into more powerful \spx@boxes@fcolorbox from sphinxpackageboxes.sty +\long\def\spx@ShadowFBox#1{% + \leavevmode + \setbox\z@\hbox{#1}% + \ifspx@topic@withshadow + \ifspx@topic@insetshadow\else + \ifdim\spx@topic@shadow@xoffset<\z@\hskip\spx@topic@shadow@xoffset\relax + \fi + \fi + \fi + \if1% use rounded boxes only if needed and possible + \ifdim\spx@topic@radius@topleft >\z@0\fi + \ifdim\spx@topic@radius@topright >\z@0\fi + \ifdim\spx@topic@radius@bottomright>\z@0\fi + \ifdim\spx@topic@radius@bottomleft >\z@0\fi + 1\spx@boxes@fcolorbox{\box\z@}% + \else + \@ifpackageloaded{pict2e}% + {\ifspx@topic@insetshadow + \spx@boxes@fcolorbox{\box\z@}% + \else + \spx@boxes@fcolorbox@rounded{\box\z@}% + \fi}% + {\spx@boxes@fcolorbox{\box\z@}}% + \fi + \ifspx@topic@withshadow + \ifspx@topic@insetshadow\else + \ifdim\spx@topic@shadow@xoffset>\z@\hskip\spx@topic@shadow@xoffset\relax + \fi + \fi + \fi } % Use framed.sty \MakeFramed/\endMakeFramed to allow page breaks for topic @@ -105,11 +114,13 @@ % more sophisticated way on usage of \MakeFramed/\endMakeFramed, and % adjusting to current text indentation. \newenvironment{sphinxShadowBox} - {\def\FrameCommand {\spx@ShadowFBox }% + {% + \spx@shadowbox@boxes@fcolorbox@setup + \def\FrameCommand {\spx@ShadowFBox }% \advance\spx@image@maxheight - -\dimexpr2\sphinxshadowrule - +2\sphinxshadowsep - +\sphinxshadowsize + -\dimexpr\spx@topic@border@top+\spx@topic@border@bottom + +\spx@topic@padding@top+\spx@topic@padding@bottom + +\ifdim\spx@topic@shadow@yoffset<\z@-\fi\spx@topic@shadow@yoffset +\baselineskip\relax % configure framed.sty not to add extra vertical spacing \ltx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}% diff --git a/sphinx/texinputs/sphinxpackageboxes.sty b/sphinx/texinputs/sphinxpackageboxes.sty index f07b9b64c8..befddf6c1f 100644 --- a/sphinx/texinputs/sphinxpackageboxes.sty +++ b/sphinx/texinputs/sphinxpackageboxes.sty @@ -2,21 +2,60 @@ % % 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 need a recent version of this package which +% allows dimensional arguments to its \moveto, \lineto, etc... but we add +% ourselves some wrappers equivalent to its v0.4a 2020/08/16 version. -% 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. +% Provides box registers \spx@tempboxa, \spx@tempboxb usable in other places +\newbox\spx@tempboxa +\newbox\spx@tempboxb + +% Internal dimens, conditionals, and color parameters involved +% in \spx@boxes@fcolorbox@setup which is to be set by callers +\newif\ifspx@boxes@withshadow +\newif\ifspx@boxes@insetshadow +\newif\ifspx@boxes@withbackgroundcolor +\newif\ifspx@boxes@withshadowcolor +\newif\ifspx@boxes@withbordercolor % -% It needs \sphinxverbatimsep, \sphinxverbatimborder and a new parameter -% \sphinxverbatimradius +\newdimen\spx@boxes@border +\newdimen\spx@boxes@border@top +\newdimen\spx@boxes@border@right +\newdimen\spx@boxes@border@bottom +\newdimen\spx@boxes@border@left % -% Executes \RequirePackage for: +\newdimen\spx@boxes@padding@top +\newdimen\spx@boxes@padding@right +\newdimen\spx@boxes@padding@bottom +\newdimen\spx@boxes@padding@left % -% - 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. +\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 in the "init" codes +% spx@boxes@bordercolor +% spx@boxes@backgroundcolor +% spx@boxes@shadowcolor +%%%%%%%%%%%%%%%% +% MACROS +% +% - \spx@boxes@fcolorbox (4 padding parameters, 4 border widths, 2 shadow widths, +% and three colors: background, border and shadow; same as in CSS styling) +% +% - \spx@boxes@fcolorbox@insetshadow (same as in CSS styling) +% +% - \spx@boxes@fcolorbox@rounded (used for code-blocks): rounded corners using +% the picture mode and pict2e package for access to PDF graphics +% This interface is WIP % 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, @@ -26,91 +65,373 @@ % (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. +% when using \spx@boxes@fcolorbox@rounded +% are done exactly as formerly; only difference is in the rounded corners. % The space occupied is same, if nothing else is changed. +\def\spx@RequirePackage@PictIIe{% \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}% + Options for setting radii 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)% - {\moveto(\strip@pt\dimexpr#1,\strip@pt\dimexpr#2)} -\def\spx@lineto(#1,#2)% - {\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{\circlearc[2]% - {\strip@pt\dimexpr#1}{\strip@pt\dimexpr#2}{\strip@pt\dimexpr#3}% + and radii setting options have been ignored}}% + \def\spx@boxes@fcolorbox@rounded{\spx@boxes@fcolorbox}% + }% +}% + + +%//// \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. +% +% The customization of the various parameters are under responsability of +% caller. At some point of code development the parameters were set +% by expansion of an \spx@boxes@fcolorbox@setup macro inside +% \spx@boxes@fcolorbox. Now this is only a hook, because the initialization +% will be done by caller rather. +\let\spx@boxes@fcolorbox@setuphook\@empty +% The same applies to \spx@boxes@fcolorbox@rounded, also with (same name) +% \spx@boxes@fcolorbox@setup left to caller configuration. +% +% The parameters are interpreted as they would as CSS properties. +% For the shadow inset variant 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 } -% 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 +\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{% -% 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 + \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 +% Would need some testing and possibly refactoring + \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 % - #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 -% work around for "old" LaTeX (we could use the "picture" package, this -% would add another dependency) - \begin{picture}% - (\strip@pt\wd\tw@,\strip@pt\dimexpr\ht\tw@+\dp\tw@)% - (\strip@pt\dimexpr-.5\sphinxverbatimborder,\strip@pt\dimexpr-.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 +% 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 +% (and not 0, only \z@...) +% 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 fot 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)% + (\strip@pt\dimexpr-.5\spx@boxes@border,\strip@pt\dimexpr-.5\spx@boxes@border)% +\ifspx@boxes@withshadow + \color{spx@boxes@shadowcolor}% + \put(\dimexpr\ifdim\spx@boxes@shadow@xoffset<\z@-\fi + 0.5\spx@boxes@border+\spx@boxes@shadow@xoffset,% + \dimexpr\ifdim\spx@boxes@shadow@yoffset<\z@\else-\fi + 0.5\spx@boxes@border-\spx@boxes@shadow@yoffset) + {\spx@boxes@borderpath\fillpath}% + {\ifspx@boxes@withbackgroundcolor\else + \color{white}% or rather try to use page color? + \spx@boxes@borderpath\fillpath + \fi}% \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 +{\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