diff options
author | Karl Berry <karl@freefriends.org> | 2015-12-06 23:50:41 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2015-12-06 23:50:41 +0000 |
commit | cf5dbf70c6bd40b1959580618f178b3f3fee09a0 (patch) | |
tree | 38650bf9d9145a14d82b9166d119b4cf49bea5a1 /Master/texmf-dist/tex/latex/longfbox | |
parent | 8b958843c92e1dc188620b20cd04a85abe4f7fbc (diff) |
longfbox (6dec15)
git-svn-id: svn://tug.org/texlive/trunk@39028 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/longfbox')
-rw-r--r-- | Master/texmf-dist/tex/latex/longfbox/longbox.sty | 853 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/longfbox/longfbox.sty | 1344 |
2 files changed, 2197 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/longfbox/longbox.sty b/Master/texmf-dist/tex/latex/longfbox/longbox.sty new file mode 100644 index 00000000000..9d373895f2b --- /dev/null +++ b/Master/texmf-dist/tex/latex/longfbox/longbox.sty @@ -0,0 +1,853 @@ +%--------------------------------------------------------------------------- +% Copyright 2015 Daan Leijen, Microsoft Corporation. +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3 +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of LaTeX +% version 2005/12/01 or later. +%--------------------------------------------------------------------------- +\NeedsTeXFormat{LaTeX2e}[1995/12/01] + +\ProvidesPackage{longbox}[2015/12/01, Daan Leijen, Provides basic longbox that can break over pages] +\RequirePackage{options} + +\@ifclassloaded{beamer}{% + \newcommand\lb@savefootnotes{}% + \newcommand\lb@restorefootnotes{}% +}% +{\RequirePackage{footnote}% + \newcommand\lb@savefootnotes{\savenotes}% + \newcommand\lb@restorefootnotes{\spewnotes}% +} + + +% -------------------------------------------------------- +% Debugging +% -------------------------------------------------------- + +\newcommand*\lb@debug[1]{% + \ontoggle{lb@debug}{\typeout{longbox debug: #1}}% +} +\newcommand*\lb@typeout[1]{% + \ontoggle{lb@verbose}{\typeout{longbox: #1}}% +} +\newcommand*\lb@warncannotsplit{% + \PackageWarning{longbox}{Cannot split box; it seems you are using a non-splittable contents}% +} +\newcommand*\lb@warnbadsplit[1]{% + \PackageWarning{longbox}{Bad split (underful vbox by \the#1)}% +} + + +% -------------------------------------------------------- +% Utilities for LaTeX internals +% -------------------------------------------------------- + +% Suppress the indentation on the following paragraph +\providecommand\nofirstindent{\@afterindentfalse\@afterheading} + +% Suppress the paragraph skip on the following paragraph +\providecommand\nofirstparskip{\addvskip{-\parskip}} + +% In contrast to addvspace, addvskip is not suppressed in a minipage +\providecommand\addvskip[1]{% + \ifvmode + \ifdim\lastskip=\z@ + \vskip #1\relax + \else + \@tempskipb#1\relax\@xaddvskip + \fi + \else\@noitemerr\fi +} + + +% Skip to 0.3\baselineskip multiple taking prevdepth into account. +\newskip\lb@prevdepth +\newcommand\lb@skiptobaseline{% + \global\lb@prevdepth=-\@m\p@\relax + \ifvmode + \ifdim\lastskip=\z@\relax + \ifdim\prevdepth=-\@m\p@\else + \dimen@\prevdepth + % Calculate the modulus of the previous depth with 0.3|\baselineskip| in |\dimen@|. + \@tempcnta\prevdepth + \@tempskipa=0.3\baselineskip\relax + \@tempcntb=\@tempskipa\relax + \divide \@tempcnta by \@tempcntb + \dimen@\prevdepth + \advance\dimen@ -\@tempcnta\@tempskipa + % Skip back by that amount, and then skip by 0.3|\baselineskip|. + \vskip -\dimen@ + \vskip \@tempskipa\relax + \global\lb@prevdepth=\@tempskipa\relax + \fi + \fi + \fi +} + +% unvbox a box, and return a vbox with a given background color +% \unvcolorbox{<colorspec>}{<vboxname>} +\newcommand\unvcolorbox[2]{% + \ifoptionblank{#1}{\vbox{\unvbox#2}}{% + \lb@debug{vcolorbox: #1}% + \vbox{\offinterlineskip + \hbox to \z@{\vbox to \z@{\optioncolor{#1}\hrule\@width\wd#2\@height\ht#2\@depth\dp#2\vss}\hss}% + \unvbox#2% + }% + }% +} + +% create a vbox with a given background color +\newcommand\vcolorbox[2]{% + \eifblank{#1}{\vbox{#2}}{% + \setbox\z@=\vbox{#2}\relax + \unvcolorbox{#1}{\z@}% + }% +}% + +% -------------------------------------------------------- +% The following macros come from mdframed +% -------------------------------------------------------- + +% Determine the amount of free space left on the current page +\newlength\lb@freevspace +\newcommand*\lb@setfreevspace@page{% + \lb@debug{ determine free space}% + \bgroup\@nobreakfalse\addpenalty\z@\egroup% + \penalty\@M\relax\vskip 2\baselineskip\relax% + \penalty9999\relax\vskip -2\baselineskip\relax% + \penalty9999% + \ifdim\pagegoal=\maxdimen\relax% + \lb@freevspace=\vsize% + \else + \lb@freevspace=\dimexpr\pagegoal-\pagetotal-\parskip\relax% + \fi + \lb@debug{free space: \the\lb@freevspace, in page: \the\textheight, vsize=\the\vsize}% +} + +\newcommand*\lb@shiftdim[2]{% + %\letoption{#1}\lb@list + \expandafter\lb@setheadtail@#1,\relax + \eifblank{\lb@head}{}{\option@invoke{/longbox/@breakat-previous}{\lb@head}}% + #2\option{/longbox/@breakat-previous}% + \eifblank{\lb@tail}{}{\let#1\lb@tail}% push back tail +} +\def\lb@comma{,}% +\def\lb@setheadtail@#1,#2\relax{% + \def\lb@head{#1}% + \def\lb@tail{#2}% adds commas! +} + +\newcommand*\lb@setfreevspace{% + \eifblank{\lb@breakat}{\lb@setfreevspace@page}{% + \def\lb@eject{\par}%no eject + \lb@extrasplit=\z@\relax% + \lb@shiftdim{\lb@breakat}\lb@freevspace + \ifdim\lb@freevspace>\z@\else\lb@setfreevspace@page\fi + }% +} + + +% Suppress overfull-underfull vbox messages +\newcommand*\lb@ignorevbadness{% + \edef\lb@currentvbadness{\the\vbadness}% + \edef\lb@currentvfuzz{\the\vfuzz}% + \vbadness=\@M\relax% + \vfuzz=\maxdimen\relax% + \afterassignment\lb@restorevbadness +} +\newcommand*\lb@restorevbadness{% + \vbadness=\lb@currentvbadness\relax + \vfuzz=\lb@currentvfuzz\relax +} + + +% -------------------------------------------------------- +% The 'long vbox' (lvbox) environment collects long material +% into a long \vbox, instead of a \hbox like a lrbox in latex. +% The collected box can contain any box, minipage, lrbox, fbox etc, +% but not outer-par material like a figure. Footnotes can be +% dealt with useing lb@savefootnotes. +% +% The material is typeset in a \vbox according to a given width. +% inside the environment, the boolean 'inlvbox' is true. +% +% \begin{lvbox}{<boxname>}{<width>} +% -------------------------------------------------------- + +\newif\ifinlvbox +\newcommand\lvbox[4]{% + \setbox#1\vbox\bgroup + \begingroup + \inlvboxtrue + % reset defaults + \let\if@nobreak\iffalse + \let\if@noskipsec\iffalse + \let\par\@@par + \let\-\@dischyph + \let\'\@acci\let\`\@accii\let\=\@acciii + % set margin and linewidth + \leftmargin=#2\relax\rightmargin=#4\relax + \@totalleftmargin=\leftmargin% + %\leftskip=#2\relax\rightskip=#4\relax\@rightskip=#4\relax + \linewidth=#3\relax + % set primitive tex margins + \leftskip=\@totalleftmargin% + \rightskip=\rightmargin% + \@rightskip=\rightmargin% + \hsize=\dimexpr\@totalleftmargin+\linewidth+\rightmargin\relax + \columnwidth\hsize + \textwidth\hsize + \nofirstindent + %\nofirstparskip +} +\def\endlvbox{\endgroup\egroup} + + + +% -------------------------------------------------------- +% +% -------------------------------------------------------- + + +\newsavebox\lb@headbox +\newsavebox\lb@savebox +\newsavebox\lb@mainbox + +% -------------------------------------------------------- +% +% -------------------------------------------------------- + +\newcommand\lb@setbaseline[1]{% + %\typeout{ set baseline, \the\dp#1,\the\ht#1}% + \ifcase\lb@baseline% + \relax%bottom + \or%middle + \setbox#1=\vbox{\hbox{\lower \dimexpr(\dp#1 + \ht#1)/2 - \dp#1\relax\vbox{\unvbox#1}}}% + \or%top + \setbox#1=\vtop{\unvbox#1}% + \fi + %\typeout{ .new dim: \the\dp#1, \the\ht#1}% +} + + +\@ifundefined{define@key}{}% + {\define@key{longbox}{options}{\options{#1}\option{/longbox/adjust-options}}}% + +\newcommand*\lb@render@breakbox{% + %\typeout{render breakbox entry (in output routine), height=\the\bb@height}% + \bb@restorekeys{longbox}% + \lb@skiptop=\ifbb@isfirst\option{/longbox/skip-top}\else\option{/longbox/skip-break-top}\fi\relax + \lb@skipbottom=\ifbb@islast\option{/longbox/skip-bottom}\else\option{/longbox/skip-break-bottom}\fi\relax + \lb@skipbreaktop=\ifbb@isfirst 0pt\else\option{/longbox/skip-break-top}\fi + \lb@skipbreakbottom=\ifbb@islast 0pt\else\option{/longbox/skip-break-bottom}\fi + %\typeout{ render: skip top=\the\lb@skiptop, bottom=\the\lb@skipbottom, break-top=\the\dimexpr\option{/longbox/skip-bottom}}% + \options{% + /longbox/@part-height=\bb@height + \lb@skipbreaktop + \lb@skipbreakbottom, + /longbox/@part-width=\option{/longbox/width} + \option{/longbox/skip-left} + \option{/longbox/skip-right},%\bb@width, + /longbox/@part-depth=0pt, + /longbox/@part-needtop=\ifbb@isfirst true\else false\fi, + /longbox/@part-needbottom=\ifbb@islast true\else false\fi, + /longbox/@content-box-height=\option{/longbox/@part-height} - \lb@skiptop - \lb@skipbottom, + /longbox/@content-box-width=\option{/longbox/width}, + /longbox/@content-box-depth=\option{/longbox/@part-depth}, + }% + %\typeout{breakbox: width=\expandafter\the\option{/longbox/width}, \the\bb@width, \the\dimexpr\option{/longbox/@part-width}}% + \vbox{% + \kern -\lb@skipbreaktop% todo: move to breakbox? + \option{/longbox/render}% + \kern -\lb@skipbreakbottom + }% +} + +\newcommand*\lb@render@vbox[1]{% + \lb@debug{render vbox entry}% + \lb@restoreoptions + \lb@skiptop=\dimexpr\iftoggle{/longbox/@part-needtop}{\option{/longbox/skip-top}}{\option{/longbox/skip-break-top}}\relax + \lb@skipbottom=\dimexpr\iftoggle{/longbox/@part-needbottom}{\option{/longbox/skip-bottom}}{\option{/longbox/skip-break-bottom}}\relax + %\typeout{ skip top=\the\lb@skiptop, bottom=\the\lb@skipbottom}% + % add top skip while maintaining the baseline. + \ifdim\lb@skiptop=\z@\relax\else + \setbox\z@=\vtop{\unvcopy#1}% + \dimen@=\ht\z@ + \setbox#1=\vbox{\offinterlineskip + \hrule width \z@ height \dimexpr\dimen@ + \lb@skiptop\relax depth -\dimen@ + \unvbox#1% + }% + \fi + % add bottom skip while maintaining the baseline. + \ifdim\lb@skipbottom=\z@\relax\else + \dimen@=\dp#1% + \setbox#1=\vbox{\offinterlineskip\unvbox#1\hrule width \z@ height -\dimen@ depth \dimexpr\dimen@ + \lb@skipbottom\relax}% + \fi + \lb@setbaseline{#1}% + \options{% + /longbox/@part-height=\dimexpr\ht#1 + \dp#1\relax, + /longbox/@part-width=\dimexpr\wd#1 + \option{/longbox/skip-left} + \option{/longbox/skip-right}\relax, + /longbox/@part-depth=\dp#1, + /longbox/@content-box-width=\option{/longbox/width}, + /longbox/@content-box-height=\option{/longbox/@part-height} - \lb@skiptop - \lb@skipbottom, + /longbox/@content-box-depth=\option{/longbox/@part-depth} - \lb@skipbottom, + }% + %\typeout{ longbox: height=\the\dimexpr\option{/longbox/@content-box-height}, outer height=\the\dimexpr\option{/longbox/@part-height}\relax}% + % lower the box depending on vertical alignment + \ifcase\option{/longbox/vertical-align/@ord}\relax + \@tempdima\z@ + \or + %bottom + \@tempdima\dimexpr0.3\baselineskip - \option{/longbox/@part-depth}\relax + \or%middle + \@tempdima\dimexpr0.5\option{/longbox/@part-height} - \option{/longbox/@part-depth}\relax + \or%top + \@tempdima\dimexpr\option{/longbox/@part-height}-\option{/longbox/@part-depth}-0.7\baselineskip\relax + \or%text-bottom + \@tempdima\dimexpr0.3\baselineskip - \option{/longbox/@part-depth}\relax + \or%text-top + \@tempdima\dimexpr\option{/longbox/@part-height}-\option{/longbox/@part-depth}-0.7\baselineskip\relax + \or%super + \@tempdima=-0.9ex% + \or%sub + \@tempdima=0.7ex% + \else + \@tempdima\z@ + \fi + \advance\@tempdima by -\option{/longbox/raise}% + \option@invoke{/longbox/@lower}{\@tempdima}% + \noindent\hbox{\lower \@tempdima\vbox{\offinterlineskip + \hbox to \z@{% + \vbox to \z@{% + \hbox{\lower \option{/longbox/@part-height}\vbox{\offinterlineskip{\option{/longbox/render}}}}% + \vss}% + \hss + }% + \hbox{% + \ifdim\option{/longbox/skip-left}=\z@\else\hskip\option{/longbox/skip-left}\fi + \box#1% + \ifdim\option{/longbox/skip-right}=\z@\else\hskip\option{/longbox/skip-right}\fi + %$\box#1% + }% + }}% +} + +\newcommand*\lb@single@[1]{% + \begingroup + \toggletrue{/longbox/@part-needtop}% + \toggletrue{/longbox/@part-needbottom}% + \lb@render@vbox{#1}% + \endgroup +} +\newcommand*\lb@first@[1]{% + \begingroup + \toggletrue{/longbox/@part-needtop}% + \togglefalse{/longbox/@part-needbottom}% + \lb@render@vbox{#1}% + \lb@eject + \endgroup +} +\newcommand*\lb@middle@[1]{% + \begingroup + \togglefalse{/longbox/@part-needtop}% + \togglefalse{/longbox/@part-needbottom}% + \lb@render@vbox{#1}% + \lb@eject + \endgroup +} +\newcommand*\lb@last@[1]{% + \begingroup + \togglefalse{/longbox/@part-needtop}% + \toggletrue{/longbox/@part-needbottom}% + \lb@render@vbox{#1}% + \endgroup +} + +% -------------------------------------------------------- +% +% -------------------------------------------------------- + +\newcommand*\lb@env@start{% + \ifcase\lb@textalign\relax + %default + \or\raggedright + \or\centering + \or\raggedleft + \else\relax% justify=default + \fi + \lb@insertbefore +} + +\newcount\lb@usevbox +\newlength\lb@width +\newlength\lb@height +\newlength\lb@skiptop +\newlength\lb@skipright +\newlength\lb@skipbottom +\newlength\lb@skipleft +\newlength\lb@skipbreaktop +\newlength\lb@skipbreakbottom +\newlength\lb@outerwidth +\newlength\lb@extrasplit +\newcount\lb@textalign +\newcount\lb@baseline +\newtoggle{lb@baselineskip}% +\newtoggle{lb@breakable}% +\newtoggle{lb@debug}% +\newtoggle{lb@verbose}% +\def\lb@breakat{}% +\def\lb@halign{}% +\def\lb@eject{}% +\def\lb@insertafter{} +\def\lb@insertbefore{} + +\newcommand*\lb@peekoptions[1]{% + % process options inside a group and just set necessary parameters + % this way, nested boxes don't influence each other's parameters + \begingroup + \options{#1}% + \option{/longbox/adjust-options}% + \protected@edef\lb@temp{\endgroup + \lb@width=\the\dimexpr\option{/longbox/width}\relax + \lb@height=\the\dimexpr\option{/longbox/height}\relax + \lb@textalign=\the\numexpr\option{/longbox/text-align/@ord}\relax + \lb@baseline=\the\numexpr\option{/longbox/baseline/@ord}\relax + \lb@skiptop=\the\dimexpr\option{/longbox/skip-top}\relax + \lb@skipright=\the\dimexpr\option{/longbox/skip-right}\relax + \lb@skipbottom=\the\dimexpr\option{/longbox/skip-bottom}\relax + \lb@skipleft=\the\dimexpr\option{/longbox/skip-left}\relax + \lb@skipbreaktop=\the\dimexpr\option{/longbox/skip-break-top}\relax + \lb@skipbreakbottom=\the\dimexpr\option{/longbox/skip-break-bottom}\relax + \lb@usevbox=\iftoggle{/longbox/use-vbox}{1}{0}\relax + \lb@outerwidth=\the\dimexpr\option{/longbox/outer-width}\relax + \lb@extrasplit=\the\dimexpr\option{/longbox/split-minimum}\relax + \def\noexpand\lb@insertafter{\option{/longbox/insert-after}}% + \def\noexpand\lb@insertbefore{\option{/longbox/insert-before}}% + \def\noexpand\lb@breakat{\option{/longbox/breakat}}% + \def\noexpand\lb@halign{\option{/longbox/height-align}}% + \def\noexpand\lb@eject{\option{/longbox/eject}}% + \noexpand\csname toggle\iftoggle{/longbox/baseline-skip}{true}{false}\endcsname{lb@baselineskip}% + \noexpand\csname toggle\iftoggle{/longbox/breakable}{true}{false}\endcsname{lb@breakable}% + \noexpand\csname toggle\iftoggle{/longbox/debug}{true}{false}\endcsname{lb@debug}% + \noexpand\csname toggle\iftoggle{/longbox/verbose}{true}{false}\endcsname{lb@verbose}% + }% + \lb@temp +} + +\newenvironment{longbox@env}[2]{% + % save options + \lb@peekoptions{#1,#2}% + % + \ifnum\lb@usevbox=0\relax + \lb@debug{start breakbox}% + \let\bb@render\lb@render@breakbox + \bb@savekeys{longbox}{options={#1,#2,outer-width=\the\lb@outerwidth}}% + \iftoggle{lb@baselineskip}{\typeout{**insert bskip}}{\typeout{**suppress bskip}\vskip 1pt}% + \begin{breakbox}% + \ifdim\lb@skiptop=\z@\relax\else\vspace{\lb@skiptop}\fi% + \dimen@=\dimexpr\linewidth-\lb@skipleft-\lb@width\relax + \begin{bb@margins}{\lb@skipleft}{\dimen@}% + \else + \lb@debug{start vbox}% + \def\lb@restoreoptions{\options{#1,#2}\option{/longbox/adjust-options}}% + \lb@savefootnotes + \dimen@=\dimexpr\linewidth-\lb@skipleft-\lb@width\relax + \lb@debug{ width=\the\lb@width, linewidth=\the\linewidth, skipleft=\the\lb@skipleft, right=\the\lb@skipright, total right=\the\dimen@}% + \iftoggle{lb@baselineskip}{\lb@skiptobaseline}{\lb@prevdepth=-\@m pt}% + \lvbox{\lb@mainbox}{0pt}{\lb@width}{0pt}%{\lb@skipleft}{\lb@width}{\lb@skipright}% + \prevdepth=\lb@prevdepth + \fi + \ifcase\lb@textalign\relax + %default + \or\raggedright + \or\centering + \or\raggedleft + \else\relax% justify=default + \fi + \lb@insertbefore + \begingroup +}{% + \par\unskip + \endgroup + \lb@insertafter + %\ifdim\lb@skipbottom=\z@\relax\else\vskip\lb@skipbottom\fi% + \ifnum\lb@usevbox=0\relax + \end{bb@margins}% + \ifdim\lb@skipbottom=\z@\relax\else\hrule width \z@ height \lb@skipbottom\fi%\vspace{\lb@skipbottom}\fi% + \iftoggle{lb@baselineskip}{}{\vskip 1sp}% + \end{breakbox}% + \lb@debug{end breakbox}% + \else + \ontoggle{lb@baselineskip}{\lb@skiptobaseline}% + \endlvbox% + \lb@debug{initial lvbox: \the\dp\lb@mainbox, \the\ht\lb@mainbox, \the\wd\lb@mainbox}% + \lb@processbox + %\setbox\lb@mainbox=\hbox{\lower \lb@skipbottom\vbox{\offinterlineskip\unvbox\lb@mainbox}}% + \lb@restorefootnotes + \lb@debug{end vbox}% + \fi +} + +\newcommand\longbox@cmd[3]{% + \begingroup + %\options{/options/collectunknown,/longbox/scoped,#2}% set scoped options first + %\option{/longbox/scoped/@adjust-options}% + \lb@peekoptions{#1,#2}% + \leavevmode + %\setbox\lb@mainbox=\hbox{% + % \begingroup + % #3% + % \endgroup + %}% + \setbox\lb@mainbox=\hbox{% + \begingroup + \ifcase\lb@textalign\relax + %default=left + \or%left + \or\hss%center + \or\hss%right + \else%justify + \fi + \lb@insertbefore + #3% + \lb@insertafter + \ifnum\lb@textalign<3\relax\hss\fi% default,left,center + \endgroup + }% + \options{#1,#2}% + \ifdim\option{/longbox/width}=-1sp\relax + \options{/longbox/width=\wd\lb@mainbox}%set to natural width + \fi + \option{/longbox/adjust-options}% + % make it a vbox + \setbox\lb@mainbox=\vbox{\offinterlineskip% + \hbox to \option{/longbox/width}{% + \unhbox\lb@mainbox + }% + }% + \def\lb@restoreoptions{}% + \letoption{/longbox/height-align}\lb@halign + \lb@height=\option{/longbox/height}\relax + \lb@baseline=\option{/longbox/baseline/@ord}\relax + \lb@processbox + \endgroup +} + +\newcommand\lb@processbox{% + \ifdim\lb@height<0pt\relax + \lb@setbaseline{\lb@mainbox}% + \else + \lb@restrictheight + \fi + \lb@typesetbox +} + +\newcommand\lb@typesetbox{% + \ifinlvbox + \iftoggle{lb@breakable}{% + %\lb@debug{disable breakable due to nesting of long-boxes}% + \togglefalse{lb@breakable}% + }{}% + \fi + \ifhmode\lb@single@{\lb@mainbox}\else\lb@typeset\fi +} + +% -------------------------------------------------------- +% +% -------------------------------------------------------- + +\newcommand\lb@restrictheight{% + \lb@typeout{restrict height to \the\lb@height}% + \lb@splitheight=\lb@height% + %lb@debug{before height split: \the\dp\lb@mainbox, \the\ht\lb@mainbox, \the\wd\lb@mainbox}% + \lb@splitbox + \ifdim\ht\lb@headbox=0pt\relax + %split failed.. do nothing + \lb@debug{could not restrict height}% + \else + % store splitted off content in the mainbox (and discard the rest) + \setbox\lb@mainbox\vbox{\unvbox\lb@headbox}% + \lb@debug{restricted height to \the\ht\lb@mainbox}% + \fi + % set baseline + \lb@setbaseline{\lb@mainbox}% + % height align + %\letoption{/longbox/height-align}\lb@halign + \eifstrequal{\lb@halign}{bottom}% + {\setbox\lb@mainbox=\vbox{\hbox{\vbox to \lb@splitheight{\vss\unvbox\lb@mainbox}}}}% + {\eifstrequal{\lb@halign}{middle}% + {\dimen@=\dimexpr\lb@splitheight-\ht\lb@mainbox-\dp\lb@mainbox\relax + \setbox\lb@mainbox=\vbox{\hbox{% + \lower \dimexpr0.5\dimen@ + \dp\lb@mainbox\relax% + \vbox to \lb@splitheight{\vss\unvbox\lb@mainbox\vss}}}}% + {% default is top + \dimen@=\dimexpr\lb@splitheight-\ht\lb@mainbox-\dp\lb@mainbox\relax + \setbox\lb@mainbox=\vbox{\vtop to \lb@splitheight{\box\lb@mainbox\vss}}% + }% + }% +} + +% -------------------------------------------------------- +% +% -------------------------------------------------------- + +\newlength\lb@neededvspace +\newcommand\lb@typeset[1][0pt]{% + \iftoggle{lb@breakable}{% + \lb@setfreevspace + \setlength\lb@neededvspace{\dimexpr\ht\lb@mainbox+\dp\lb@mainbox+\lb@skiptop+\lb@skipbottom\relax}% + \lb@debug{needed: \the\lb@neededvspace, available: \the\lb@freevspace}% + \ifdim\lb@neededvspace<\lb@freevspace\relax + \lb@single@{\lb@mainbox}% + \else + \lb@typeout{longbox needs splitting}% + \setlength\lb@splitheight{\dimexpr\lb@freevspace-\lb@skiptop-\lb@skipbreakbottom\relax}% + \lb@splitbox + \ifdim\ht\lb@headbox=0pt\relax + % failed to split + \ifdim\dimexpr\lb@freevspace + #1\relax<\textheight\relax % test if we were at a fresh page.. (and prevent infinite recursion) + \lb@debug{failed to split the box, inserting a page break}% + \hrule \@height\z@ \@width\hsize + \lb@eject% + \lb@typeset[\textheight]% try again, but pass \textheight to guard against infinite recursion + \else + % on a fresh page we should not fail anymore.. just output as is.. + % lb@warncannotsplit + \lb@single@{\lb@mainbox}% + \fi + \else + % first part success + \lb@typeout{first part splitted}% + \lb@first@{\lb@headbox}% + \expandafter\expandafter\expandafter\lb@typesetrest + \fi + \fi + }{%\else + \lb@debug{unbreakable box}% + \lb@single@{\lb@mainbox}% always directly output an unbreakable box + }% +} + +\newcommand\lb@typesetrest{% + \lb@setfreevspace% + \setlength\lb@neededvspace{\dimexpr\ht\lb@mainbox+\dp\lb@mainbox+\lb@skipbottom+\lb@skipbreaktop\relax}% + \ifdim\lb@neededvspace<\lb@freevspace\relax + \lb@typeout{output last part of box}% + \lb@last@{\lb@mainbox}% + \else + \lb@debug{split box further}% + \setlength\lb@splitheight{\dimexpr\lb@freevspace-\lb@skipbreaktop-\lb@skipbreakbottom\relax}% + \lb@splitbox + \ifdim\ht\lb@headbox=0pt\relax + % failed to split + \lb@typeout{failed to split box!}% + \lb@last@{\lb@mainbox}% + \else + % middle part success + \lb@typeout{output middle part of box}% + \lb@middle@{\lb@headbox}% + \expandafter\expandafter\expandafter\lb@typesetrest% continue the iteration... + \fi + \fi +} + +% -------------------------------------------------------- +% Split a long vbox over multiple pages. +% This code is based on similar code in the mdframed package +% -------------------------------------------------------- + +\newlength\lb@splitheight +\newlength\lb@insurance % tiny extra space to ensure our box will really fit +\setlength\lb@insurance{1pt} + +% expects split target height in lb@splitheight, and splits off the start of lb@mainbox to lb@headbox +\newcommand\lb@splitbox{% + \ifdim\dimexpr\ht\lb@mainbox + \dp\lb@mainbox\relax>\lb@splitheight\relax + % the main box is larger than our target split height.. + \ifdim\lb@extrasplit>\lb@splitheight\relax + % not enough space to bother + \lb@typeout{not enough space on page for a split}% + \setbox\lb@headbox=\vbox{}% empty head + \else + % try a split; lower the split height a bit so we are sure to fit + \advance\lb@splitheight -\lb@insurance\relax + \lb@debug{split: \the\lb@splitheight, from \the\dimexpr\ht\lb@mainbox + \dp\lb@mainbox\relax}% + \setbox\lb@savebox=\vbox{\unvcopy\lb@mainbox}% save original + \lb@trysplit{\lb@splitheight}% + \ifdim\dimexpr\ht\lb@headbox + \dp\lb@headbox>\lb@splitheight\relax + % too big, bad split. Try other splits.. iterate N times with 1 or 5pt less before giving up + \dimen@=\lb@splitheight\relax + \@tempcnta=\z@\relax + \loop + \ifdim\dimexpr\ht\lb@headbox+\dp\lb@headbox\relax>\lb@splitheight\relax + \ifnum\@tempcnta<50% + \advance\dimen@ by -\p@\relax% try a slightly smaller height.. + \else + \advance\dimen@ by -5\p@\relax% try larger increase after 50pt.. + \fi + \advance\@tempcnta by \@ne\relax + \lb@ignorevbadness + \setbox\lb@mainbox=\vbox{\unvcopy\lb@savebox}% restore + \lb@trysplit{\dimen@}% + \ifdim\lb@extrasplit<\dimen@\relax\else\lb@splitstop\fi % don't try to split too small + \ifnum\@tempcnta<100\relax\else\lb@splitstop\fi % and not more than N attempts + \repeat% + \ifnum\@tempcnta<100\relax + \dimen@=\dimexpr\lb@splitheight - \ht\lb@headbox - \dp\lb@headbox\relax + \ifdim\dimen@>\option{/longbox/split-badness}\relax + \lb@warnbadsplit{\dimen@}% + \fi + \fi + \fi + \fi + \else + % mainbox fits in our target lb@splitheight + \setbox\lb@headbox=\vbox{\unvbox\lb@mainbox}% + \setbox\lb@mainbox=\vbox{}% + \fi +} + +\newcommand\lb@splitstop{% + \lb@typeout{cannot find a good split}% + \let\iterate\relax + \lb@warncannotsplit + \setbox\lb@mainbox=\vbox{\unvcopy\lb@savebox}% restore + \setbox\lb@headbox=\vbox{}% empty head + \@tempcnta=\@M\relax +} + +\newcommand\lb@trysplit[1]{% try to split at given height + \lb@typeout{try to split at: \the\dimexpr #1\relax}% + \lb@ignorevbadness + \setbox\lb@headbox=\vsplit\lb@mainbox to #1\relax% + \setbox\lb@headbox=\vbox{\unvbox\lb@headbox}% + \setbox\lb@mainbox=\vbox{\unvbox\lb@mainbox}% +} + +% -------------------------------------------------------- +% The longbox environment uses options to set its options +% -------------------------------------------------------- + + +% keys and styles that can be set once globally +\options{% + /longbox/.new family, +}% + +\options{/longbox,% + % computed + @part-needtop/.new toggle, + @part-needbottom/.new toggle, + @part-height/.new length, + @part-width/.new length, + @part-depth/.new length, + @content-box-height/.new length, + @content-box-width/.new length, + @content-box-depth/.new length, + @breakat-previous/.new length, + @lower/.new length, + % + debug/.new toggle, + verbose/.new toggle, + render/.new value =\lb@render@fbox, + adjust-options/.new value = {\longbox@adjustoptions}, + eject/.new value = {\protect\vfill\protect\eject}, + use-vbox/.new toggle = true, + split-minimum/.new length = {1.5\baselineskip}, + split-badness/.new length = \baselineskip, + % + height-align/.new choice= {top,middle,bottom}, + baseline/.new choice = {bottom,middle,top}, + text-align/.new choice = {default,left,center,right,justify}, + vertical-align/.new choice = {baseline,bottom,middle,top,text-bottom,text-top,super,sub}, + raise/.new length = {0pt}, + baseline-skip/.new toggle =true, + % + height/.new length = -1sp, + width/.new length = -1sp, + outer-height/.new length= -1sp, + outer-width/.new length = -1sp, + insert-before/.new value= {}, + insert-after/.new value = {}, + breakat/.new value = {}, + breakable/.new toggle = false, + skip/.new style = {skip-top=#1,skip-right=#1,skip-bottom=#1,skip-left=#1}, + skip-top/.new length, + skip-right/.new length, + skip-bottom/.new length, + skip-left/.new length, + skip-break-bottom/.new length, + skip-break-top/.new length, +} + +\newcommand\longbox@adjustoptions{% + %\typeout{ standard longbox adjustoptions}% + \lb@debug{ current width=\the\dimexpr\option{/longbox/width}, outer=\the\dimexpr\option{/longbox/outer-width}, linewidth=\the\linewidth}% + \ontoggle{/longbox/debug}{\option@invoke{/longbox/verbose}{true}}% + % adjust height + \ifdim\option{/longbox/height}=-1sp\relax + \ifdim\option{/longbox/outer-height}=-1sp\else + \option@invoke{/longbox/height}% + {\option{/longbox/outer-height}-\option{/longbox/skip-top}-\option{/longbox/skip-bottom}}% + \fi + \fi + % set width + \ifdim\option{/longbox/width}=-1sp\relax + \ifdim\option{/longbox/outer-width}=-1sp\relax + \option@invoke{/longbox/outer-width}{\linewidth}% + \fi + \dimen@=\dimexpr\option{/longbox/outer-width}-\option{/longbox/skip-left}-\option{/longbox/skip-right}\relax + \ifdim\dimen@<\z@\relax\dimen@=\z@\fi + \option@invoke{/longbox/width}{\dimen@}% + \fi + % use a breakbox whenever we are in external vertical mode and not width or height restricted. + \iftoggle{/longbox/use-vbox}{}{% + \ifinner\toggletrue{/longbox/use-vbox}\else + \ifhmode\toggletrue{/longbox/use-vbox}\else + \ifdim\option{/longbox/height}>-1sp\toggletrue{/longbox/use-vbox}\else + \iftoggle{/longbox/breakable}{}{\toggletrue{/longbox/use-vbox}}% + \ifoptionblank{/longbox/breakat}{}{\toggletrue{/longbox/use-vbox}}% + \fi\fi\fi + }% +} + +\newenvironment{longbox}[1][]{% + %\bb@savekeys{bfbox}{fboxrule=\the\fboxrule,fboxsep=\the\fboxsep,bgcolor={\bb@bgcolor},rulecolor={\bb@rulecolor},stickout={\bb@stickout}}% + \begin{longbox@env}{/longbox}{#1}% +}{\end{longbox@env}} + +\newcommand\lbox[1][]{% + %\bb@savekeys{bfbox}{fboxrule=\the\fboxrule,fboxsep=\the\fboxsep,bgcolor={\bb@bgcolor},rulecolor={\bb@rulecolor},stickout={\bb@stickout}}% + \longbox@cmd{/longbox}{#1}% +} + +\newcommand*\lb@render@fbox{% + %\typeout{render defaultbox: bgcolor=\bb@bgcolor, needtop=\iftoggle{/longbox/@part-needtop}{true}{false}}% + \@ovdx=\dimexpr\option{/longbox/@part-width} - 2\fboxrule\relax% + \@ovdy=\dimexpr\option{/longbox/@part-height}\relax% + \iftoggle{/longbox/@part-needbottom}% + {\@tempdima=0pt\relax\advance\@ovdy by -\fboxrule}% + {\@tempdima=\dimexpr\fboxrule + \bb@stickout\relax + \advance\bb@height by \@tempdima + \advance\@ovdy by \@tempdima}% + \iftoggle{/longbox/@part-needtop}% + {\@tempdimb=0pt\relax\advance\@ovdy by -\fboxrule}% + {\@tempdimb=\dimexpr\bb@stickout\relax + \advance\bb@height by \@tempdimb + \advance\@ovdy by \@tempdimb}% + % + \hbox{\lower \@tempdima\vbox{% + \vskip -\@tempdimb + \ontoggle{/longbox/@part-needtop}{\lb@debug{toprule wd=\expandafter\the\option{/longbox/width}}\hrule width \option{/longbox/@part-width} height \fboxrule}% + \hbox{% + \vrule width \fboxrule height \@ovdy% + \ifx\bb@bgcolor\@empty + \vrule width \@ovdx height \z@\relax + \else + {\color{\bb@bgcolor}\vrule width \@ovdx height \@ovdy}% + \fi + \vrule width \fboxrule height \@ovdy% + }% + \ontoggle{/longbox/@part-needbottom}{\hrule width \option{/longbox/@part-width} height \fboxrule}% + }}% +}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/longfbox/longfbox.sty b/Master/texmf-dist/tex/latex/longfbox/longfbox.sty new file mode 100644 index 00000000000..9627964199d --- /dev/null +++ b/Master/texmf-dist/tex/latex/longfbox/longfbox.sty @@ -0,0 +1,1344 @@ +%--------------------------------------------------------------------------- +% Copyright 2015 Daan Leijen, Microsoft Corporation. +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3 +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of LaTeX +% version 2005/12/01 or later. +%--------------------------------------------------------------------------- +\NeedsTeXFormat{LaTeX2e}[1995/12/01] + +\ProvidesPackage{longfbox}[2015/12/01, Daan Leijen, Provides long fbox that can break over pages] + +\RequirePackage{options} +\RequirePackage{longbox} +\RequirePackage{pict2e} +\RequirePackage{ellipse} + +% -------------------------------------------------------- +% Dimension calulations +% -------------------------------------------------------- + +% dimmin/dimmax return minimum or maximum dimension +\providecommand\dim@min[2]{\ifdim#1>#2#2\else #1\fi} +\providecommand\dim@max[2]{\ifdim#1>#2#1\else #2\fi} + +\newcommand*\option@dimmin[2]{\dim@min{\option{#1}}{\option{#2}}} +\newcommand*\option@dimmax[2]{\dim@max{\option{#1}}{\option{#2}}} + + +% -------------------------------------------------------- +% Add a new 'sides' option type +% -------------------------------------------------------- + +\options{ + /handlers/new sides/.new handler = []{ + \ifblank{#2}% + {\option@def{#1/@cmd@sides}##1##2##3##4{\optionsalso{#1-top={##1}, #1-right={##2}, #1-bottom={##3}, #1-left={##4}}}}% + {\option@def{#1/@cmd@sides}##1##2##3##4{\optionsalso{#2}}}% + \optionsalso{ + #1/.new cmdx = {##1,##2,##3,##4,##5\relax}{,,,,\relax}{% + \ifblank{##2##3##4}{\option{#1/@cmd@sides}{##1}{##1}{##1}{##1}}% + {\ifblank{##3##4}{\option{#1/@cmd@sides}{##1}{##2}{##1}{##2}}% + {\ifblank{##4}{\option{#1/@cmd@sides}{##1}{##2}{##3}{##2}}% + {\option{#1/@cmd@sides}{##1}{##2}{##3}{##4}}% + }% + }% + }, + #1/.type = sides, + }% + },% +} + +\newcommand*\optionlengthlimit[3]{% len, min, max + \letoption{#1}\opt@temp + \ifdim\opt@temp<\dimexpr#2\relax + \option@invoke{#1}{#2}% + \else\ifdim\opt@temp>\dimexpr#3\relax + \option@invoke{#1}{#3}% + \fi\fi +} + +\newcommand*\optionradiuslimit[4]{% r1, r2, min, max + \letoption{#1}\opt@tempa + \letoption{#2}\opt@tempb + \ifdim\opt@tempa<\dimexpr#3\relax\option@invoke{#1}{#3}\fi + \ifdim\opt@tempb<\dimexpr#3\relax\option@invoke{#2}{#3}\fi + \ifdim\dimexpr\opt@tempa + \opt@tempb\relax=\z@\relax\else + \ifdim\dimexpr\opt@tempa+\opt@tempb\relax>\dimexpr#4\relax + \edef\opt@perc{\the\numexpr(\number\dimexpr#4\relax)/% + (\number\dimexpr(\opt@tempa+\opt@tempb)/100\relax)}% + %\typeout{scale:\the\opt@tempa,\the\opt@tempb, by \opt@perc percent to make \the\dimexpr#4\relax}% + \edef\opt@temp{\dimexpr\opt@perc\dimexpr\the\opt@tempa\relax / 100\relax}% + \option@einvoke{#1}{\opt@temp}% + \option@einvoke{#2}{\dimexpr#4 - \opt@temp\relax}% + %\typeout{ scaled to: \the\opt@temp,\the\dimexpr#4 - \opt@temp\relax}% + \fi + \fi +} + + +% \begin{macro}{\trig@atantan} +% \marg{a}\marg{b}\marg{$\alpha$}{dimen$_\mathit{reg}$}\\ +% Assigns $\atan_2(\frac{\sin(\alpha)}{b},\frac{\cos(\alpha)}{a})$ to dimension register \textit{dimen$_\mathit{reg}$}, +% where $a$ and $b$ are dimensions. +% Returns $\alpha$ when $a = b$, or when $a=0$ or $b=0$. +% \begin{macrocode} +\newcommand*\trig@atantan[4]{% + %\typeout{ atantan:(\the#1,\the#2,\the#3, #4)}% + \@tempdima\dimexpr#1\relax + \@tempdimb\dimexpr#2\relax +% \end{macrocode} +% If $a = b$, we have a circle and the result is $\alpha$. +% \begin{macrocode} + \ifdim\@tempdima=\@tempdimb + #4\dimexpr#3\relax + \else\ifdim\@tempdima=\z@ + #4\dimexpr#3\relax + \else\ifdim\@tempdimb=\z@ + #4\dimexpr#3\relax + \else + \edef\trig@temp{\strip@pt\dimexpr#3\relax}% + \CalculateSin{\trig@temp}\CalculateCos{\trig@temp}% + \@tempdimc\dimexpr1\p@ * \dimexpr\UseSin{\trig@temp}\p@\relax/\@tempdimb\relax + \@tempdimd\dimexpr1\p@ * \dimexpr\UseCos{\trig@temp}\p@\relax/\@tempdima\relax + \pIIe@atantwo{\@tempdimc}{\@tempdimd}\dimen@ + \ifdim\dimen@<\z@ + \ifdim\dimexpr#3\relax<\z@\else\advance\dimen@360\p@\fi + \fi + \@tempdima\dimexpr#3 - \dimen@\relax + \ifdim\@tempdima<\z@\@tempdima-\@tempdima\fi + \ifdim\@tempdima<360\p@\else\advance\dimen@360\p@\fi + %\typeout{atan: \the\dimexpr#3\relax versus. \the\dimen@ }% + #4\dimen@ + \fi\fi\fi +} +% \end{macrocode} +% \end{macro} + +% rough approximation of the perimeter; +% if |radius-x == radius-y| = 0 (a circle), the approximation is precise. +% otherwise, works best when |angle2-angle1| <= 45 and gets worse from there on. +\newcommand*\ellip@letarcperimeter[5]{% 'radius-x', 'radius-y', 'angle-1', 'angle-2', '\result' + \@tempdima\dimexpr#3\relax + \@tempdimb\dimexpr#4\relax + \@tempdimc\dimexpr\@tempdima - \@tempdimb\relax + \ifdim\@tempdimc<\z@\@tempdimc-\@tempdimc\fi + \ifdim#1=#2\relax% circle? + \edef\@tempa{\strip@pt\@tempdimc}% angle difference delta as factor + \dimen@\@tempa\dimexpr#1\relax% r*delta + \dimen@0.017453\dimen@% (2*pi/360) * r * delta = 2*pi*r * (delta/360) + \else% ellipse: take the distance between the points on the ellipse, works pretty good if delta <= 45, and ok'ish for delta <= 90 + \@ovro\dimexpr#1\relax + \@ovri\dimexpr#2\relax + \edef\fbox@tempa{\strip@pt\@tempdima}% + \edef\fbox@tempb{\strip@pt\@tempdimb}% + \pIIe@ellip@sincost{\fbox@tempa}{\fbox@tempb}% + \@tempdima\@ellipcosone\@ovro + \@tempdimb\@ellipsinone\@ovri + \@tempdimc\@ellipcostwo\@ovro + \@tempdimd\@ellipsintwo\@ovri + \advance\@tempdimc by -\@tempdima% + \advance\@tempdimd by -\@tempdimb% + \pIIe@ellip@csqrt{\@tempdimc}{\@tempdimd}{\dimen@}% + %\typeout{ distance: \the\dimen@, from (x,y)=(\the\@tempdimc,\the\@tempdimd), radii=(\the#1,\the#2), angles=(\the#3,\the#4)}% + \fi + \edef#5{\the\dimen@}% +} + + +% ------------------------------------------------------------------------------ +% Borders using the picture environment +% ------------------------------------------------------------------------------ + +\newcommand*\fbox@border@pict{% + \ifnum\option{/fbox/render/@ord}=2\relax% + \begingroup + \hbox{% + \unitlength\p@ + \begin{picture}(0,0)(0,\optionunit{/fbox/@border-box-height})% bottom-left is origin + % markers + \ontoggle{/fbox/show-markers}{% + \linethickness{\option{/fbox/marker-width}}% + \optioncolor{/fbox/marker-color}% + \fbox@rect{0pt}{0pt}{\option{/fbox/@border-box-width}}{\option{/fbox/@border-box-height}}% + \fbox@rect{\option{/fbox/border-left-width}}{\option{/fbox/border-\fbox@bottom-width}}% + {\option{/fbox/@border-box-width}-\option{/fbox/border-right-width}}% + {\option{/fbox/@border-box-height}-\option{/fbox/border-\fbox@top-width}}%S + }% + %compute corner coordinates + \fbox@border@calccorners + %put down the background color + \fbox@border@colorbackground + \option{/fbox/picture-insert-before}% + %put down the sides + \fbox@border@side{3}{-2}{0}%top + \fbox@border@side{5}{-4}{3}%left + \fbox@border@side{-6}{7}{2}%bottom + \fbox@border@side{-8}{1}{1}%right + \end{picture}% + }% + \endgroup + \fi +} + +\newcommand*\fbox@border@pict@after{% + \ifnum\option{/fbox/render/@ord}=2\relax% + \letoption{/fbox/picture-insert-after}\fbox@insertafter + \eifblank{\fbox@insertafter}{}{% + \begingroup + \hbox{% + \begin{picture}(0,0)(0,0)% bottom-left is origin + \fbox@insertafter + \end{picture}% + }% + \endgroup + }% + \fi +} + +\newcommand*\fbox@border@side[3]{% + \fbox@setoct@angles{#1}% + \edef\fbox@style{\option{/fbox/border-\fbox@side-style}}% + \optioncolor{/fbox/border-\fbox@side-color}% + \option{/fbox/picture-side-insert-before}% + \ifcsdef{fbox@border@pict@\fbox@style}% + {\csuse{fbox@border@pict@\fbox@style}{#1}{#2}{#3}}% + {\PackageWarning{longfbox}{Unknown style "\fbox@style". Using "solid" instead.}% + \fbox@border@pict@solid{#1}{#2}{#3}}% + \option{/fbox/picture-side-insert-after}% +} + +% ------------------------------------------------------------------------------ +% Define standard border styles for the picture environment +% +% a style has the form \fbox@border@pict@<style>{<octant1>}{<octant2>}{<side no>} +% where <side> is the border side no: top=0, right=1, bottom=2, left=3 + + +\newcommand*\fbox@border@pict@none[3]{% + % do nothing +} +\newcommand*\fbox@border@pict@hidden[3]{% + % do nothing +} + +% -------------------------------------------------------- +% Background color +% -------------------------------------------------------- + +% Lay down background color +\newcommand*\fbox@border@colorbackground{% + \ifcase\option{/fbox/background-clip/@ord}\relax + \fbox@border@colorbackground@border + \edefoption{/fbox/background-border-color}\@tempa + \edefoption{/fbox/background-padding-color}\@tempb + \ifx\@tempa\@tempb\relax\else + \fbox@border@colorbackground@padding + \fi + \or + \fbox@border@colorbackground@padding + \or + \fbox@border@colorbackground@content + \fi +} + +\newcommand*\fbox@border@colorbackground@padding{% + \ifoptionblank{/fbox/background-padding-color}{}{% + \optioncolor{/fbox/background-padding-color}% + \moveto(\optionunit{/fbox/@border-bottom-left-ix},\optionunit{/fbox/border-\fbox@bottom-width})% + \fbox@cornerarc{bottom-left}{i}{270}{180}% + \fbox@cornerarc{top-left}{i}{180}{90}% + \fbox@cornerarc{top-right}{i}{90}{0}% + \fbox@cornerarc{bottom-right}{i}{0}{-90}% + \closepath + \fillpath + \edefoption{/fbox/background-padding-color}\@tempa + \edefoption{/fbox/background-color}\@tempb + \ifx\@tempa\@tempb\relax\else + \fbox@border@colorbackground@content + \fi + }% +} + +\newcommand*\fbox@border@colorbackground@content{% + \ifoptionblank{/fbox/background-color}{}{% + \optioncolor{/fbox/background-color}% + \@ovxx=\dimexpr\option{/fbox/border-left-width} + \option{/fbox/padding-left}\relax + \@ovyy=\dimexpr\option{/fbox/border-\fbox@bottom-width} + \option{/fbox/padding-\fbox@bottom}\relax + \fbox@rect*{\@ovxx}{\@ovyy}% + {\@ovxx + \option{/fbox/@content-box-width}}% + {\@ovyy + \option{/fbox/@content-box-height}}% + }% +} + +\newcommand*\fbox@border@colorbackground@border{% + \ifoptionblank{/fbox/background-border-color}{}{% + \optioncolor{/fbox/background-border-color}% + \moveto(0,0)% + \fbox@cornerarc{bottom-left}{}{270}{180}% + \fbox@cornerarc{top-left}{}{180}{90}% + \fbox@cornerarc{top-right}{}{90}{0}% + \fbox@cornerarc{bottom-right}{}{0}{-90}% + \closepath + \fillpath + }% +} + +\newcommand*\fbox@cornerarc[4]{% {'top-left'}{'i'?}{'start angle'}{'end angle'} + \elliparc{\optionunit{/fbox/@border-#1-#2x}}% + {\optionunit{/fbox/@border-#1-#2y}}% + {\optionunit{/fbox/@border-#1-#2radius-x}}% + {\optionunit{/fbox/@border-#1-#2radius-y}}{#3}{#4}% +} + + + +% -------------------------------------------------------- +% Compute corner coordinates +% -------------------------------------------------------- + +% Calculate all corner coordinates +\newcommand*\fbox@border@calccorners{% + \fbox@border@calccorner{top}{left}{\fbox@top}% + \fbox@border@calccorner{top}{right}{\fbox@top}% + \fbox@border@calccorner{bottom}{left}{\fbox@bottom}% + \fbox@border@calccorner{bottom}{right}{\fbox@bottom}% +} + +% calculate for each corner +% the /fbox/@border-#1-#2- +% -iradius-x/y: inner corner radius +% -ix/iy: inner corner center point +\newcommand*\fbox@border@calccorner[3]{% {'top'}{'left'}{'break-top'} + \option@invoke{/fbox/@border-#1-#2-iradius-x}{\dimexpr0pt\relax}% + \option@invoke{/fbox/@border-#1-#2-iradius-y}{\dimexpr0pt\relax}% + % only give positive inner radius if the center lays outside the border + \ifdim\dimexpr\option{/fbox/@border-#1-#2-radius-x} - \option{/fbox/border-#2-width}\relax>0pt\relax + \ifdim\dimexpr\option{/fbox/@border-#1-#2-radius-y} - \option{/fbox/border-#3-width}\relax>0pt\relax + \option@invoke{/fbox/@border-#1-#2-iradius-x}% + {\option{/fbox/@border-#1-#2-radius-x} - \option{/fbox/border-#2-width}}% + \option@invoke{/fbox/@border-#1-#2-iradius-y}% + {\option{/fbox/@border-#1-#2-radius-y} - \option{/fbox/border-#3-width}}% + \fi + \fi + % assign inner (ix,iy) and outer (x,y) + \option@invoke{/fbox/@border-#1-#2-ix}{\option{/fbox/border-#2-width} + \option{/fbox/@border-#1-#2-iradius-x}}% + \option@invoke{/fbox/@border-#1-#2-iy}{\option{/fbox/border-#3-width} + \option{/fbox/@border-#1-#2-iradius-y}}% + \ifstrequal{#2}{left}{}{% + \option@invoke{/fbox/@border-#1-#2-ix}{\option{/fbox/@border-box-width} - \option{/fbox/@border-#1-#2-ix}}% + }% + \ifstrequal{#1}{bottom}{}{% + \option@invoke{/fbox/@border-#1-#2-iy}{\option{/fbox/@border-box-height} - \option{/fbox/@border-#1-#2-iy}}% + }% + % assign dividing angle based on the width ratio 90 * (b / (a+b)) + \ifdim\option{/fbox/border-#3-width}=\z@\relax + \@tempdima=90pt\relax + \else + \@tempdima90\dimexpr1pt * \option{/fbox/border-#2-width}/(\option{/fbox/border-#3-width} + \option{/fbox/border-#2-width})\relax + \fi + %\trig@atantwo{\option{/fbox/border-#2-width}}{\option{/fbox/border-#1-width}}\@tempdima + \ifstrequal{#2}{left}{\@tempdima\dimexpr180\p@-\@tempdima\relax}{}% + \ifstrequal{#1}{bottom}{\@tempdima\dimexpr360\p@-\@tempdima\relax}{}% + \option@invoke{/fbox/@border-#1-#2-phi}{\@tempdima}% + %\typeout{ corner angle #1-#2: \the\option{/fbox/@border-#1-#2-phi}}% +} + +% -------------------------------------------------------- +% Helper coordinates +% There are all just definitions of 'dimexpr's +% -------------------------------------------------------- + +\options{ + /fbox/@border-top-left-x/.new dim = \option{/fbox/@border-top-left-radius-x}, + /fbox/@border-top-left-y/.new dim = \option{/fbox/@border-box-height} - \option{/fbox/@border-top-left-radius-y}, + /fbox/@border-top-right-x/.new dim = \option{/fbox/@border-box-width} - \option{/fbox/@border-top-right-radius-x}, + /fbox/@border-top-right-y/.new dim = \option{/fbox/@border-box-height} - \option{/fbox/@border-top-right-radius-y}, + /fbox/@border-bottom-left-x/.new dim = \option{/fbox/@border-bottom-left-radius-x}, + /fbox/@border-bottom-left-y/.new dim = \option{/fbox/@border-bottom-left-radius-y}, + /fbox/@border-bottom-right-x/.new dim = \option{/fbox/@border-box-width} - \option{/fbox/@border-bottom-right-radius-x}, + /fbox/@border-bottom-right-y/.new dim = \option{/fbox/@border-bottom-right-radius-y}, + % the following ones are only used for sharp corner filling; perhaps we can optimize this better? + /fbox/@border-top-y/.new dim = \option{/fbox/@border-box-height}, + /fbox/@border-top-iy/.new dim = \option{/fbox/@border-box-height} - \option{/fbox/border-\fbox@top-width}, + /fbox/@border-bottom-y/.new dim = 0pt, + /fbox/@border-bottom-iy/.new dim = \option{/fbox/border-\fbox@bottom-width}, + /fbox/@border-right-x/.new dim = \option{/fbox/@border-box-width}, + /fbox/@border-right-ix/.new dim = \option{/fbox/@border-box-width} - \option{/fbox/border-right-width}, + /fbox/@border-left-x/.new dim = 0pt, + /fbox/@border-left-ix/.new dim = \option{/fbox/border-left-width}, + /fbox/@border-top-left-ox/.new dim = \option@dimmax{/fbox/@border-top-left-x}{/fbox/@border-top-left-ix}, + /fbox/@border-top-left-oy/.new dim = \option@dimmin{/fbox/@border-top-left-y}{/fbox/@border-top-left-iy}, + /fbox/@border-top-right-ox/.new dim = \option@dimmin{/fbox/@border-top-right-x}{/fbox/@border-top-right-ix}, + /fbox/@border-top-right-oy/.new dim = \option@dimmin{/fbox/@border-top-right-y}{/fbox/@border-top-right-iy}, + /fbox/@border-bottom-left-ox/.new dim = \option@dimmax{/fbox/@border-bottom-left-x}{/fbox/@border-bottom-left-ix}, + /fbox/@border-bottom-left-oy/.new dim = \option@dimmax{/fbox/@border-bottom-left-y}{/fbox/@border-bottom-left-iy}, + /fbox/@border-bottom-right-ox/.new dim= \option@dimmin{/fbox/@border-bottom-right-x}{/fbox/@border-bottom-right-ix}, + /fbox/@border-bottom-right-oy/.new dim= \option@dimmax{/fbox/@border-bottom-right-y}{/fbox/@border-bottom-right-iy}, +} + + +% -------------------------------------------------------- +% setoct: Set various macros based on the octant +% -------------------------------------------------------- + + +\newcount\fbox@oct +\newcount\fbox@quad +\newcount\fbox@diaq +\newcount\fbox@sign + +%fbox@corner +\newcommand*\fbox@setoct[2][]{% [i (inner)]{octant}} + \fbox@sign1\relax + \fbox@oct#2\relax + \ifnum\fbox@oct<\z@\fbox@oct-\fbox@oct\fbox@sign-\fbox@sign\fi + \fbox@quad\fbox@oct + \advance\fbox@quad by 1\relax + \divide\fbox@quad by 2\relax% quadrant 1-4 + \ifcase\fbox@quad\relax%\@tempa\relax + \or\def\fbox@corner{top-right}% + \or\def\fbox@corner{top-left}% + \or\def\fbox@corner{bottom-left}% + \or\def\fbox@corner{bottom-right}% + \fi + \letcs\fbox@adjustx{fbox@adjustx@\fbox@corner}% + \letcs\fbox@adjusty{fbox@adjusty@\fbox@corner}% + \fbox@diaq\fbox@oct + \divide\fbox@diaq by 2\relax% 'diamond quadrant' 0 -4 + \ifodd\fbox@diaq\toggletrue{/fbox/@side-horizontal}\def\fbox@axis{x}\else\togglefalse{/fbox/@side-horizontal}\def\fbox@axis{y}\fi + \ifcase\fbox@diaq\relax + \def\fbox@side{right}% + \or\iftoggle{/longbox/@part-needtop}{\def\fbox@side{top}}{\def\fbox@side{break-top}}% + \or\def\fbox@side{left}% + \or\iftoggle{/longbox/@part-needbottom}{\def\fbox@side{bottom}}{\def\fbox@side{break-bottom}}% + \or\def\fbox@side{right}% + \fi + \option@invoke{/fbox/@side}{\fbox@side}% + %\typeout{setoct(#1,#2): \fbox@corner: \iftoggle{/fbox/@side-horizontal}{hor}{ver} diaq=\the\fbox@diaq, quad=\the\fbox@quad, oct=\the\fbox@oct, direction=\the\fbox@sign}% +} + +\newcommand*\fbox@setotherside{% + \ifcase\fbox@diaq\relax + \def\fbox@otherside{top}% + \or\ifodd\fbox@oct\relax\def\fbox@otherside{left}\else\def\fbox@otherside{right}\fi% + \or\ifodd\fbox@oct\relax\def\fbox@otherside{bottom}\else\def\fbox@otherside{top}\fi + \or\ifodd\fbox@oct\relax\def\fbox@otherside{right}\else\def\fbox@otherside{left}\fi + \or\def\fbox@otherside{bottom}% + \fi +} + +\csdef{fbox@adjustx@top-right}#1{\dimexpr\option{/fbox/@border-box-width} - #1\relax}% +\csdef{fbox@adjusty@top-right}#1{\dimexpr\option{/fbox/@border-box-height} - #1\relax}% + +\csdef{fbox@adjustx@top-left}#1{#1}% +\csdef{fbox@adjusty@top-left}#1{\dimexpr\option{/fbox/@border-box-height} - #1\relax}% + +\csdef{fbox@adjustx@bottom-left}#1{#1}% +\csdef{fbox@adjusty@bottom-left}#1{#1}% + +\csdef{fbox@adjustx@bottom-right}#1{\dimexpr\option{/fbox/@border-box-width} - #1\relax}% +\csdef{fbox@adjusty@bottom-right}#1{#1}% + + +\newlength\fbox@anglestart +\newlength\fbox@angleend +\newcommand*\fbox@setoct@angles[2][]{% + \fbox@setoct[#1]{#2}% + \fbox@anglestart\dimexpr90\p@ * \fbox@diaq\relax + \fbox@angleend\option{/fbox/@border-\fbox@corner-phi}% + \ifnum\fbox@sign<\z@ + \ifodd\fbox@oct\relax\else + \@tempdima\fbox@anglestart + \fbox@anglestart\fbox@angleend + \fbox@angleend\@tempdima + \fi + \else + \ifodd\fbox@oct\relax + \@tempdima\fbox@anglestart + \fbox@anglestart\fbox@angleend + \fbox@angleend\@tempdima + \fi + \fi + %\typeout{ angles=\the\fbox@anglestart, to \the\fbox@angleend}% +} + + +% -------------------------------------------------------- +% Solid border +% -------------------------------------------------------- + +\newcommand*\fbox@border@pict@solid[3]{% octant1, octant2, side no. + %\fbox@setoct@angles[]{#1}% + %\optioncolor{/fbox/border-\fbox@side-color}% + \fbox@border@hcornerarc[1]{}{#1}% + \fbox@setoct@angles{-#2}% + \fbox@border@hcornerarc{}{-#2}% + \fbox@setoct@angles[i]{#2}% + \fbox@border@hcornerarc{i}{#2}% + \fbox@setoct@angles[i]{-#1}% + \fbox@border@hcornerarc{i}{-#1}% + \closepath + \fillpath +} + +% a half corner arc; assumes zero radius will just draw a line to the center point +\newcommand*\fbox@border@hcornerarc[3][0]{% [lmn], i(nner), octant + \elliparc[#1]{\optionunit{/fbox/@border-\fbox@corner-#2x}}% + {\optionunit{/fbox/@border-\fbox@corner-#2y}}% + {\optionunit{/fbox/@border-\fbox@corner-#2radius-x}}% + {\optionunit{/fbox/@border-\fbox@corner-#2radius-y}}{\strip@pt\fbox@anglestart}{\strip@pt\fbox@angleend}% +} + +% -------------------------------------------------------- +% Double border +% -------------------------------------------------------- + +\newcommand*\fbox@border@pict@double[3]{% octant1, octant2, side no + \fbox@setoct@angles{#1}% + \fbox@border@hcornerarc@[1]{}{#1}{0}% + \fbox@setoct@angles{-#2}% + \fbox@border@hcornerarc@{}{-#2}{0}% + \fbox@setoct@angles[i]{#2}% + \fbox@border@hcornerarc@{}{#2}{0.33}% + \fbox@setoct@angles[i]{-#1}% + \fbox@border@hcornerarc@{}{-#1}{0.33}% + \closepath + \fillpath + % + \fbox@setoct@angles{#1}% + \fbox@border@hcornerarc@[1]{}{#1}{0.66}% + \fbox@setoct@angles{-#2}% + \fbox@border@hcornerarc@{}{-#2}{0.66}% + \fbox@setoct@angles[i]{#2}% + \fbox@border@hcornerarc@{}{#2}{1}% + \fbox@setoct@angles[i]{-#1}% + \fbox@border@hcornerarc@{}{-#1}{1}% + \closepath + \fillpath +} + +% a half corner arc; but only over 'fraction' of the border width +% assumes zero radius will just draw a line to the center point +\newcommand*\fbox@border@hcornerarc@[4][0]{% [lmn], i(nner), octant, width fraction + % determine radius and center point for the width fraction + \fbox@setotherside + \iftoggle{/fbox/@side-horizontal}% + {\@tempdima#4\option{/fbox/border-\fbox@otherside-width}% + \@tempdimb#4\option{/fbox/border-\fbox@side-width}}% + {\@tempdimb#4\option{/fbox/border-\fbox@otherside-width}% + \@tempdima#4\option{/fbox/border-\fbox@side-width}}% + \@tempdimc\fbox@adjustx{\@tempdima}% + \@tempdima\dimexpr\option{/fbox/@border-\fbox@corner-radius-x} - \@tempdima\relax + \ifdim\@tempdima<\z@ + \@tempdima\z@ + \else + \@tempdimc\option{/fbox/@border-\fbox@corner-x}% + \fi + \@tempdimd\fbox@adjusty{\@tempdimb}% + \@tempdimb\dimexpr\option{/fbox/@border-\fbox@corner-radius-y} - \@tempdimb\relax + \ifdim\@tempdimb<\z@ + \@tempdimb\z@ + \else + \@tempdimd\option{/fbox/@border-\fbox@corner-y}% + \fi + \edef\fbox@radiusx{\strip@pt\@tempdima}% + \edef\fbox@radiusy{\strip@pt\@tempdimb}% + \edef\fbox@x{\strip@pt\@tempdimc}% + \edef\fbox@y{\strip@pt\@tempdimd}% + %\typeout{radius:\fbox@radiusx,\fbox@radiusy}% + \elliparc[#1]{\fbox@x}{\fbox@y}% + {\fbox@radiusx}{\fbox@radiusy}% + {\strip@pt\fbox@anglestart}{\strip@pt\fbox@angleend}% +} + +% -------------------------------------------------------- +% Groove and Ridge border +% -------------------------------------------------------- + +% draw a side border +\newtoggle{fbox@innerdark}% +\newcommand*\fbox@border@pict@groove{% octant1, octant2, side no + \ifnum\fbox@oct>5\toggletrue{fbox@innerdark}\else\togglefalse{fbox@innerdark}\fi + \fbox@border@pict@grooved% +} +\newcommand*\fbox@border@pict@ridge{% octant1, octant2, side no + \ifnum\fbox@oct<6\toggletrue{fbox@innerdark}\else\togglefalse{fbox@innerdark}\fi + \fbox@border@pict@grooved% +} + +\newcommand*\fbox@border@pict@grooved[3]{% octant, octant, side no + \iftoggle{fbox@innerdark}{}% + {\color{\option{/fbox/border-\fbox@side-color}\option{/fbox/border-dark-mix}}}% + \fbox@setoct@angles{#1}% + \fbox@border@hcornerarc@[1]{}{#1}{0}% + \fbox@setoct@angles{-#2}% + \fbox@border@hcornerarc@{}{-#2}{0}% + \fbox@setoct@angles[i]{#2}% + \fbox@border@hcornerarc@{}{#2}{0.5}% + \fbox@setoct@angles[i]{-#1}% + \fbox@border@hcornerarc@{}{-#1}{0.5}% + \closepath + \fillpath + % + \iftoggle{fbox@innerdark}% + {\color{\option{/fbox/border-\fbox@side-color}\option{/fbox/border-dark-mix}}}% + {\optioncolor{/fbox/border-\fbox@side-color}}% + \fbox@setoct@angles{#1}% + \fbox@border@hcornerarc@[1]{}{#1}{0.5}% + \fbox@setoct@angles{-#2}% + \fbox@border@hcornerarc@{}{-#2}{0.5}% + \fbox@setoct@angles[i]{#2}% + \fbox@border@hcornerarc@{}{#2}{1}% + \fbox@setoct@angles[i]{-#1}% + \fbox@border@hcornerarc@{}{-#1}{1}% + \closepath + \fillpath +} + +% -------------------------------------------------------- +% Inset and outset border +% -------------------------------------------------------- + +\newcommand*\fbox@border@pict@inset{% octant1, octant2, side no + \ifnum\fbox@oct<6\relax\color{\option{/fbox/border-\fbox@side-color}\option{/fbox/border-dark-mix}}\fi + \fbox@border@pict@inoutset +} +\newcommand*\fbox@border@pict@outset{% octant1, octant2, side no + \ifnum\fbox@oct>5\relax\color{\option{/fbox/border-\fbox@side-color}\option{/fbox/border-dark-mix}}\fi + \fbox@border@pict@inoutset +} +\newcommand*\fbox@border@pict@inoutset[3]{% octant1, octant2, side no + \fbox@border@hcornerarc[1]{}{#1}% + \fbox@setoct@angles{-#2}% + \fbox@border@hcornerarc{}{-#2}% + \fbox@setoct@angles[i]{#2}% + \fbox@border@hcornerarc{i}{#2}% + \fbox@setoct@angles[i]{-#1}% + \fbox@border@hcornerarc{i}{-#1}% + \closepath + \fillpath +} + + + +% -------------------------------------------------------- +% Dashed & Dotted +% -------------------------------------------------------- +\newtoggle{fbox@dotted} +\newlength\fbox@dash +\newlength\fbox@dashskip + + +\newcommand*\fbox@border@pict@dotted{% octant1, octant2, side no + \toggletrue{fbox@dotted}% + \fbox@border@pict@dashed@% +} + +\newcommand*\fbox@border@pict@dashed{% octant1, octant2, side no + \togglefalse{fbox@dotted}% + \fbox@border@pict@dashed@% +} + +\newcommand*\fbox@border@pict@dashed@[3]{% octant1, octant2; side no; (shared between dotted and dashed + % calculate corner lengths + \fbox@setoct@angles{#2}% + \edef\fbox@cornerb{\fbox@corner}%% + \iftoggle{fbox@dotted} + {\fbox@dash\option{/fbox/border-\fbox@side-width}% + \fbox@dashskip\option{/fbox/border-\fbox@side-dotskip}}% + {\fbox@dash\option{/fbox/border-\fbox@side-dash}% + \fbox@dashskip\option{/fbox/border-\fbox@side-dashskip}}% + \fbox@let@cornerlen\fbox@blen% + % + \fbox@setoct@angles{#1}% + \edef\fbox@cornera{\fbox@corner}% + \fbox@let@cornerlen\fbox@alen% + %\typeout{dashed \fbox@side: alen:\fbox@alen, blen:\fbox@blen }% + % + % calculate dash skip + \dimen@\dimexpr\option{/fbox/@border-\fbox@cornera-o\fbox@axis} - \option{/fbox/@border-\fbox@cornerb-o\fbox@axis}\relax + \ifdim\dimen@<0pt\relax\dimen@-\dimen@\fi + \advance\dimen@ by \dimexpr\fbox@alen + \fbox@blen\relax% total outer border length + \@tempdima\dimexpr\fbox@dash + \fbox@dashskip\relax% initial estimate of full dash + \@tempcnta\number\dimen@ + \divide\@tempcnta by \number\@tempdima% full dashes that fit in the total + \@tempdimb\dimexpr\dimen@ - \the\@tempcnta\fbox@dash\relax% total skip space + \fbox@dashskip\dimexpr\@tempdimb/\the\@tempcnta\relax% final dashskip such that it fits nicely + \edef\fbox@dashfull{\the\dimexpr \fbox@dash + \fbox@dashskip\relax}% + %\typeout{ dash \fbox@side: \the\dimexpr\fbox@dash\relax, skip:\fbox@dashskip}% + % + \optioncolor{/fbox/border-\fbox@side-color}% + \fbox@dashcorner{\fbox@alen}% + \dimen@\dimexpr\fbox@alen - (\fbox@dashskip/2)\relax + \@tempcnta\number\dimen@ + \divide\@tempcnta by \number\dimexpr\fbox@dashfull\relax + \advance\dimen@ by -\dimexpr\fbox@dashfull * \@tempcnta\relax + %\typeout{ delta \fbox@side - \fbox@corner: \the\fbox@delta, versus \the\dimen@}% + \fbox@delta\dimen@ + \fbox@dashside% + \fbox@setoct@angles{#2}% again :( + \fbox@dashcorner{\fbox@blen}% +} + +\newcommand*\fbox@dashside{% ', + %\typeout{** dash: \iftoggle{/fbox/@side-horizontal}{hor}{ver}, \fbox@side, diaq=\the\fbox@diaq}% + \dimen@\dimexpr\option@dimmax{/fbox/@border-\fbox@cornera-o\fbox@axis}{/fbox/@border-\fbox@cornera-i\fbox@axis}\relax% + \@tempdima\dimexpr\option@dimmin{/fbox/@border-\fbox@cornerb-o\fbox@axis}{/fbox/@border-\fbox@cornerb-i\fbox@axis}\relax% + \ifdim\fbox@delta>\z@\relax + \ifdim\fbox@delta<\fbox@dash\relax + %\rule{\dimexpr\fbox@dash - #2}{#3}% + \fbox@dashdraw{\dimexpr\dimen@\relax}{\dimexpr\fbox@dash - \fbox@delta\relax}% + %\typeout{- add small rule and skip: \the\dimexpr\fbox@dash - \fbox@delta\relax, \fbox@dashskip}% + \else + %\typeout{- add just skip: \the\dimexpr\fbox@dashfull - \fbox@delta}% + \fi + \advance\dimen@ by \dimexpr\fbox@dashfull - \fbox@delta\relax% + \fi + \@whiledim\dimen@<\@tempdima\do{% + \advance\dimen@\fbox@dash\relax% + \ifdim\dimen@>\@tempdima\relax% + %\typeout{final dash: \the\dimen@, \fbox@dash, \the\dimexpr\fbox@dash + \@tempdima - \dimen@\relax}% + \fbox@dashdraw{\dimexpr\dimen@ - \fbox@dash\relax}{\dimexpr\fbox@dash + \@tempdima - \dimen@ + 0.1\p@\relax}% + \else + \fbox@dashdraw{\dimen@}{-\fbox@dash}% + \fi + \advance\dimen@\fbox@dashskip\relax% + }% +} + +\newcommand*\fbox@dashdraw[2]{% x/y dash-len + \iftoggle{fbox@dotted}% + {\fbox@from\option{/fbox/border-\fbox@side-width}%% + \@tempdimb\dimexpr#2\relax% + \ifdim\@tempdimb=-\fbox@dash\relax + \iftoggle{/fbox/@side-horizontal}% + {\put(\strip@pt\dimexpr#1 + #2/2\relax,\strip@pt\dimexpr\fbox@adjusty{0.5\fbox@from}\relax){\circle*{\strip@pt\fbox@from}}}% + {\put(\strip@pt\dimexpr\fbox@adjustx{0.5\fbox@from}\relax,\strip@pt\dimexpr#1 + #2/2\relax){\circle*{\strip@pt\fbox@from}}}% + \fi + }% + {\iftoggle{/fbox/@side-horizontal}% + {\fbox@rect*{#1}{\fbox@adjusty{0pt}}{\dimexpr#1 + #2\relax}{\fbox@adjusty{\option{/fbox/border-\fbox@side-width}}}}% + {\fbox@rect*{\fbox@adjustx{0pt}}{#1}{\fbox@adjustx{\option{/fbox/border-\fbox@side-width}}}{\dimexpr #1 + #2}}% + }% +} + +\newcommand*\fbox@rect{\@ifstar{\@tempswatrue\fbox@rect@}{\@tempswafalse\fbox@rect@}}% +\newcommand*\fbox@rect@[4]{% + %\typeout{rect: #1,#2 - #3,#4}% + \edef\fbox@tempa{\opt@unit{#1}}% + \edef\fbox@tempb{\opt@unit{#2}}% + \edef\fbox@tempc{\opt@unit{#3}}% + \edef\fbox@tempd{\opt@unit{#4}}% + \moveto(\fbox@tempa,\fbox@tempb)% + \lineto(\fbox@tempa,\fbox@tempd)% + \lineto(\fbox@tempc,\fbox@tempd)% + \lineto(\fbox@tempc,\fbox@tempb)% + \closepath + \if@tempswa\fillpath\else\strokepath\fi +} + +% -------------------------------------------------------- +% dashed corner +% -------------------------------------------------------- + +\newcommand*\fbox@let@cornerlen[1]{% \resultlen + \ellip@letarcperimeter{\option{/fbox/@border-\fbox@corner-radius-x}}{\option{/fbox/@border-\fbox@corner-radius-y}}% + {\fbox@anglestart}{\fbox@angleend}#1% + \ifdim\option{/fbox/@border-\fbox@corner-iradius-\fbox@axis}>\z@\relax\else + % add abs|ix-x| to the calculated alen + %\typeout{ sharp corner \fbox@corner: adjust}% + \iftoggle{fbox@dotted}% + {\dimen@\dimexpr\fbox@dash\relax}% + {\dimen@\dimexpr\option{/fbox/@border-\fbox@corner-i\fbox@axis}-\option{/fbox/@border-\fbox@corner-\fbox@axis}\relax% + \ifdim\dimen@<\z@\relax \dimen@-\dimen@\fi + \advance\dimen@ by \dimexpr#1\relax + %\typeout{ unadjust len: \the\dimen@}% + % now adjust to look good later on since we will always fill a sharp corner + \ifdim\dimen@>\fbox@dash\relax\dimen@\fbox@dash\fi + }% + \edef#1{\the\dimexpr\dimen@ + (\fbox@dashskip/2)\relax}% + \fi + %\typeout{ corner length: \fbox@side - \fbox@corner: #1}% +}% + +\newcommand*\fbox@dashcorner[1]{%'\corner length '' + \ifdim\option{/fbox/@border-\fbox@corner-iradius-x}>\z@%\fbox@dashfull\relax + % draw rounded dashes + \fbox@dash@roundedcorner{#1}% + \else + \iftoggle{fbox@dotted}% + {% get mininum width + \@tempdima\dimexpr\option{/fbox/@border-\fbox@corner-ix}-\option{/fbox/@border-\fbox@corner-x}\relax + \ifdim\@tempdima<\z@\@tempdima-\@tempdima\fi + \@tempdimb\dimexpr\option{/fbox/@border-\fbox@corner-iy}-\option{/fbox/@border-\fbox@corner-y}\relax + \ifdim\@tempdimb<\z@\@tempdimb-\@tempdimb\fi + \ifdim\@tempdimb<\@tempdima\@tempdima\@tempdimb\fi + % radius of corner circle is half + \@tempdima0.5\@tempdima + \edef\fbox@radius{\strip@pt\@tempdima}% + % determine center + \ifnum\fbox@quad>2 + \@tempdimb\dimexpr\option{/fbox/@border-\fbox@corner-iy} - \@tempdima\relax + \else + \@tempdimb\dimexpr\option{/fbox/@border-\fbox@corner-iy} + \@tempdima\relax + \fi + \ifnum\fbox@quad=2 + \@tempdima\dimexpr\option{/fbox/@border-\fbox@corner-ix} - \@tempdima\relax + \else\ifnum\fbox@quad=3 + \@tempdima\dimexpr\option{/fbox/@border-\fbox@corner-ix} - \@tempdima\relax + \else + \@tempdima\dimexpr\option{/fbox/@border-\fbox@corner-ix} + \@tempdima\relax + \fi\fi + % determine angles + \@tempdimc\numexpr(\fbox@quad - 1) * 90 + 45\relax\p@ + \@tempdimd\dimexpr\@tempdimc + 180\p@\relax + \edef\fbox@temp{\number\fbox@oct}% + \ifodd\fbox@temp + \advance\@tempdimc by -180\p@ + \advance\@tempdimd by -180\p@ + \fi + %\typeout{ half circle: \fbox@side - \fbox@corner, \the\@tempdimc -> \the\@tempdimd}% + \edef\fbox@anglea{\strip@pt\@tempdimc}% + \edef\fbox@angleb{\strip@pt\@tempdimd}% + \put(\strip@pt\@tempdima,\strip@pt\@tempdimb){\arc*[\fbox@anglea,\fbox@angleb]{\fbox@radius}}% + }% + {\ifdim\option{/fbox/@border-\fbox@corner-radius-x}>\z@% + % an inside sharp corner, fill. + %\typeout{draw sharp }% + \moveto(\optionunit{/fbox/@border-\fbox@corner-ix},\optionunit{/fbox/@border-\fbox@corner-iy})% inner corner + \iftoggle{/fbox/@side-horizontal}% + {\lineto(\optionunit{/fbox/@border-\fbox@corner-ox},\optionunit{/fbox/@border-\fbox@side-iy}) + \lineto(\optionunit{/fbox/@border-\fbox@corner-ox},\optionunit{/fbox/@border-\fbox@side-y})} + {\lineto(\optionunit{/fbox/@border-\fbox@side-ix},\optionunit{/fbox/@border-\fbox@corner-oy}) + \lineto(\optionunit{/fbox/@border-\fbox@side-x},\optionunit{/fbox/@border-\fbox@corner-oy})} + %\fbox@border@hcornerarc{}{}{#3}{}% + \elliparc{\optionunit{/fbox/@border-\fbox@corner-x}}% + {\optionunit{/fbox/@border-\fbox@corner-y}}% + {\optionunit{/fbox/@border-\fbox@corner-radius-x}}% + {\optionunit{/fbox/@border-\fbox@corner-radius-y}}{\strip@pt\fbox@angleend}{\strip@pt\fbox@anglestart}% + \closepath\fillpath + \else + % a non-rounded corner, draw a triangle + %\typeout{draw sharp - \fbox@corner, axis=\fbox@axis} + \moveto(\optionunit{/fbox/@border-\fbox@corner-ix},\optionunit{/fbox/@border-\fbox@corner-iy})% inner corner + \lineto(\optionunit{/fbox/@border-\fbox@corner-x},\optionunit{/fbox/@border-\fbox@corner-y})% outer corner + \iftoggle{/fbox/@side-horizontal}% + {\lineto(\optionunit{/fbox/@border-\fbox@corner-ix},\optionunit{/fbox/@border-\fbox@corner-y})}% outside opposite inner corner + {\lineto(\optionunit{/fbox/@border-\fbox@corner-x},\optionunit{/fbox/@border-\fbox@corner-iy})}% outside opposite inner corner + \closepath + \fillpath + \fi + }% + \fi +} + +% -------------------------------------------------------- +% Dashed rounded corner +% -------------------------------------------------------- + +\newlength\fbox@anglecur +%\newlength\fbox@angleend +\newlength\fbox@dashangle +\newlength\fbox@dashskipangle +\newlength\fbox@delta +\newlength\fbox@from +\newlength\fbox@to + +\newcommand*\fbox@dash@roundedcorner[1]{% 'corner len' + %\typeout{ dash corner: \fbox@side - \fbox@corner, len=#1, start,end=\the\fbox@anglestart,\the\fbox@angleend}% + \trig@atantan{\option{/fbox/@border-\fbox@corner-radius-x}}{\option{/fbox/@border-\fbox@corner-radius-y}}{\fbox@anglestart}\fbox@anglestart% + \trig@atantan{\option{/fbox/@border-\fbox@corner-radius-x}}{\option{/fbox/@border-\fbox@corner-radius-y}}{\fbox@angleend}\fbox@angleend% + % + \fbox@delta\dimexpr\fbox@angleend - \fbox@anglestart\relax% + \fbox@dashangle\dimexpr \fbox@delta * \dimexpr\fbox@dash\relax / \dimexpr#1\relax% + \fbox@dashskipangle\dimexpr \fbox@delta * \dimexpr\fbox@dashskip\relax / \dimexpr#1\relax% + %\typeout{ delta=\the\fbox@delta, dash angle=\the\fbox@dashangle, skip angle=\the\fbox@dashskipangle}% + \advance\fbox@anglestart by 0.5\fbox@dashskipangle% start with skip + \ifdim\fbox@dashangle<\z@\relax\edef\fbox@cmp{>}\else\edef\fbox@cmp{<}\fi + \@whiledim\fbox@anglestart\fbox@cmp\fbox@angleend\do\fbox@dash@roundedcornerdash% +} + +\newcommand*\fbox@dash@roundedcornerdash{% + \fbox@from\fbox@anglestart + \advance\fbox@anglestart by \fbox@dashangle + \ifdim\fbox@angleend\fbox@cmp\fbox@anglestart\relax + %\typeout{too much? \the\fbox@anglestart, and \the\fbox@angleend}% + \fbox@to\fbox@angleend + \else + \fbox@to\fbox@anglestart + \fi + \iftoggle{fbox@dotted}% + {% take mid angle + \fbox@to\fbox@anglestart + \advance\fbox@to\fbox@from + \divide\fbox@to by 2 + \edef\fbox@angle{\strip@pt\fbox@to}% + \CalculateSin{\fbox@angle}\CalculateCos{\fbox@angle}% + % calculate inner and middle point on the ellipse + \fbox@from\UseCos{\fbox@angle}\option{/fbox/@border-\fbox@corner-iradius-x}% + \fbox@to\UseSin{\fbox@angle}\option{/fbox/@border-\fbox@corner-iradius-y}% + \@tempdima0.5\dimexpr\option{/fbox/@border-\fbox@corner-radius-x} + \option{/fbox/@border-\fbox@corner-iradius-x}\relax + \@tempdimb0.5\dimexpr\option{/fbox/@border-\fbox@corner-radius-y} + \option{/fbox/@border-\fbox@corner-iradius-y}\relax + \@tempdima\UseCos{\fbox@angle}\@tempdima + \@tempdimb\UseSin{\fbox@angle}\@tempdimb + % use circle radius of distance between inner and middle point + \advance\fbox@from by -\@tempdima + \advance\fbox@to by -\@tempdimb + \pIIe@ellip@csqrt{\fbox@from}{\fbox@to}\dimen@% cache csqrt since for fixed width this is always the same + \edef\fbox@temp{\strip@pt\dimexpr2\dimen@\relax}% + %\typeout{ (a,b)=(\the\@tempdima,\the\@tempdimb), (c,d)=(\the\fbox@from,\the\fbox@to), distance=\the\dimen@}% + % move to center and draw + \advance\@tempdima by \dimexpr\option{/fbox/@border-\fbox@corner-x}\relax% + \advance\@tempdimb by \dimexpr\option{/fbox/@border-\fbox@corner-y}\relax% + \put(\strip@pt\@tempdima,\strip@pt\@tempdimb){\circle*{\fbox@temp}}% + }% + {\edef\fbox@from@{\strip@pt\fbox@from}% + \edef\fbox@to@{\strip@pt\fbox@to}% + % draw a rounded dash + \@ovro\option{/fbox/@border-\fbox@corner-radius-x}% + \@ovri\option{/fbox/@border-\fbox@corner-radius-y}% + \pIIe@elliparc@t{1}{\option{/fbox/@border-\fbox@corner-x}}{\option{/fbox/@border-\fbox@corner-y}}% + {\fbox@from@}{\fbox@to@}% + % and for the inner circle + \@ovro\option{/fbox/@border-\fbox@corner-iradius-x}% + \@ovri\option{/fbox/@border-\fbox@corner-iradius-y}% + \pIIe@elliparc@t{0}{\option{/fbox/@border-\fbox@corner-ix}}{\option{/fbox/@border-\fbox@corner-iy}}% + {\fbox@to@}{\fbox@from@}% + + \closepath + \fillpath + }% + \advance\fbox@anglestart by \fbox@dashskipangle% +} + + + +% ------------------------------------------------------------------------------ +% Define standard border styles +% +% a style has the form \fbox@border@plain@<style>{<side-name>}{<border-width>}{<total length>} +% where <side> is the border side +% <direction> is either "h" or "v" (horizontal or vertical) +% <borderwidth> the width of the rule +% +% predefined styles: none, hidden, solid, transparent, and dashed + +\newcommand*\fbox@border@plain@none[3]{} +\newcommand*\fbox@border@plain@hidden[3]{} + +\newcommand*\fbox@border@plain@transparent[3]{% + \iftoggle{/fbox/@side-horizontal}% + {\hrule width #3 height \z@\relax}% + {\vrule width \z@ height #3\relax}% +} + +\newcommand*\fbox@border@plain@solid[3]{% + \iftoggle{/fbox/@side-horizontal}% + {\hrule width #3 height #2\relax}% + {\vrule width #2 height #3\relax}% +} + +\newcommand*\fbox@border@plain@dashed[3]{% + \iftoggle{/fbox/@side-horizontal}% + {\edef\fbox@dash{\vrule width \option{/fbox/border-#1-dash} height #2}% + \edef\fbox@dashskip{\hskip \option{/fbox/border-#1-dashskip} plus 0.25ex minus 0.25ex}% + \hbox to #3{\fbox@dash\fbox@dashskip\xleaders\hbox{\fbox@dash\fbox@dashskip}\hfill\fbox@dash}}% + {\edef\fbox@dash{\hrule height \option{/fbox/border-#1-dash} width #2}% + \edef\fbox@dashskip{\vskip \option{/fbox/border-#1-dashskip} plus 0.25ex minus 0.25ex}% + \vbox to #3{\offinterlineskip\fbox@dash\fbox@dashskip\xleaders\vbox{\fbox@dash\fbox@dashskip}\vfill\fbox@dash}}% +} + +\newcommand*\fbox@border@plain@dotted[3]{% + \iftoggle{/fbox/@side-horizontal}% + {\edef\fbox@dot{\vrule width #2 height #2}% + \edef\fbox@dotskip{\hskip \option{/fbox/border-#1-dotskip} plus 0.5ex minus 0.1ex}% + \hbox to #3{\xleaders\hbox{\fbox@dot\fbox@dotskip}\hfill\hbox{\fbox@dot}}}% + {\edef\fbox@dot{\hrule height #2 width #2}% + \edef\fbox@dotskip{\vskip \option{/fbox/border-#1-dotskip} plus 0.5ex minus 0.1ex}% + \vbox to #3{\fbox@dotskip\offinterlineskip\cleaders\vbox{\fbox@dot\fbox@dotskip}\vfill}}% +} + +% -------------------------------------------------------- +% +% -------------------------------------------------------- +\newcommand\fbox@setdim{% + %\typeout{ set dim}% + \iftoggle{/longbox/@part-needtop}{\def\fbox@top{top}}{\def\fbox@top{break-top}}% + \iftoggle{/longbox/@part-needbottom}{\def\fbox@bottom{bottom}}{\def\fbox@bottom{break-bottom}}% + \options{% + /fbox/@padding-box-height=\option{/fbox/@content-box-height}% full height (including depth) + +\option{/fbox/padding-\fbox@top} +\option{/fbox/padding-\fbox@bottom},% + /fbox/@padding-box-depth=\option{/fbox/@content-box-depth} + \option{/fbox/padding-\fbox@bottom},% + /fbox/@padding-box-width=\option{/fbox/@content-box-width}% + +\option{/fbox/padding-left}+\option{/fbox/padding-right}, + /fbox/@border-box-width=\option{/fbox/@padding-box-width}% + +\option{/fbox/border-left-width}+\option{/fbox/border-right-width},% + /fbox/@border-box-height=\option{/fbox/@padding-box-height}% full height + +\option{/fbox/border-\fbox@top-width}% + +\option{/fbox/border-\fbox@bottom-width},% + /fbox/@border-box-depth=\option{/fbox/@padding-box-depth}% + +\option{/fbox/border-\fbox@bottom-width},% + }% + % lower/raise for break boxes + %\@tempdima=\z@\relax + %\advance\@tempdima by \dimexpr\option{/fbox/padding-\fbox@bottom} + \option{/fbox/margin-\fbox@bottom} + \option{/fbox/border-\fbox@bottom-width}\relax% + %\advance\@tempdima by -\dimexpr\option{/fbox/padding-\fbox@top} + \option{/fbox/margin-\fbox@top} + \option{/fbox/border-\fbox@top-width}\relax% + %\option@invoke{/fbox/@lower}{\@tempdima}% + % limit radius + \optionradiuslimit{/fbox/@border-top-left-radius-y}{/fbox/@border-bottom-left-radius-y}% + {0pt}{\option{/fbox/@border-box-height}}% + \optionradiuslimit{/fbox/@border-top-right-radius-y}{/fbox/@border-bottom-right-radius-y}% + {0pt}{\option{/fbox/@border-box-height}}% + \optionradiuslimit{/fbox/@border-top-left-radius-x}{/fbox/@border-top-right-radius-x}% + {0pt}{\option{/fbox/@border-box-width}}% + \optionradiuslimit{/fbox/@border-bottom-left-radius-x}{/fbox/@border-bottom-right-radius-x}% + {0pt}{\option{/fbox/@border-box-width}}%\ + % switch to plain mode if this is a simple box; todo: is it worth to do this test? + \ifnum\option{/fbox/render/@ord}=0\relax + \option@invoke{/fbox/render}{plain}% + \def\fbox@stylex{}% + \def\fbox@colorx{}% + \def\do##1{% + \letoption{/fbox/border-##1-style}\fbox@style + \eifstrequal{\fbox@style}{none}{}{% + \option@ifanyof{\fbox@style}{solid,dashed}{% + \eifblank{\fbox@stylex}{\let\fbox@stylex\fbox@style}{% + \ifx\fbox@style\fbox@stylex\else\option@invoke{/fbox/render}{picture}\expandafter\listbreak\fi + }% + }{\option@invoke{/fbox/render}{picture}\listbreak}% + }% + \letoption{/fbox/border-##1-color}\fbox@color + \eifblank{\fbox@colorx}{\let\fbox@colorx\fbox@color}{% + \ifx\fbox@color\fbox@colorx\else\option@invoke{/fbox/render}{picture}\expandafter\listbreak\fi + }% + }% + \docsvlist{top,left,bottom,right,break-top,break-bottom}% + \ifnum\option{/fbox/render/@ord}=1\relax + \def\do##1{% + \ifdim\option{/fbox/@border-##1-radius-x}=\z@\relax\else\option@invoke{/fbox/render}{picture}\expandafter\listbreak\fi + \ifdim\option{/fbox/@border-##1-radius-y}=\z@\relax\else\option@invoke{/fbox/render}{picture}\expandafter\listbreak\fi + }% + \docsvlist{top-left,top-right,bottom-left,bottom-right}% + \fi + \ifnum\option{/fbox/render/@ord}=1\relax + \def\do##1{% + \letoption{/fbox/picture-##1}\fbox@temp + \eifblank{\fbox@temp}{}{\option@invoke{/fbox/render}{picture}\listbreak}% + }% + \docsvlist{insert-before,insert-after,side-insert-before,side-insert-after}% + \fi + \fi +} + +\newrobustcmd*\fbox@border@plain[2]{% + \ifnum\option{/fbox/render/@ord}<2\relax + \begingroup + \option@invoke{/fbox/@side}{#1}% + \ifx#2h\relax + \toggletrue{/fbox/@side-horizontal}% + \def\fbox@length{\option{/fbox/@border-box-width}}% + \else + \togglefalse{/fbox/@side-horizontal}% + \def\fbox@length{\option{/fbox/@padding-box-height}}% + \fi% + \edef\fbox@rendername{fbox@border@plain@\option{/fbox/border-#1-style}}% + \optioncolor{/fbox/border-#1-color}% set color already + \option{/fbox/plain-side-insert-before}% + \ifcsdef{\fbox@rendername}% + {\csuse{\fbox@rendername}{#1}{\option{/fbox/border-#1-width}}{\fbox@length}}% + {\PackageWarning{longfbox}{Unknown (plain) border style "\option{/fbox/border-#1-style}": using "solid" instead}{}% + \fbox@border@plain@solid{#1}{\option{/fbox/border-#1-width}}{\fbox@length}}% + \option{/fbox/plain-side-insert-after}% + \endgroup + \else + \kern\option{/fbox/border-#1-width}% + \fi +} + +\newrobustcmd*\fbox@kern[3][]{% + \iftoggle{/fbox/show-markers}{% + \begingroup + \optioncolor{/fbox/marker-color}% + \ifx#2v\relax + \def\fbox@marker{\vrule width \option{/fbox/marker-width} height \option{#3}}% + \eifblank{#1}{\hbox{\fbox@marker}}{\vbox{\hbox to \option{#1}{\fbox@marker\hfill\hfill\fbox@marker}}}% + \else + \def\fbox@marker{\vrule height \option{/fbox/marker-width} width \option{#3}}% + \setlength\dimen@{\option{/fbox/marker-width}}% + \eifblank{#1}{}{\advance\dimen@ \dimexpr -\option{#1}\relax\relax}% + \lower \dimen@\hbox{\fbox@marker}% + \fi + \endgroup + }% + {\kern\option{#3}}% +} + +\newrobustcmd*\fbox@plain@bgcolor[1]{% + \ifnum\option{/fbox/render/@ord}<2\relax + \ifoptionblank{/fbox/background-#1-color}{}{% + \vtop to 0pt{% + \hbox to 0pt{% + \optioncolor{/fbox/background-#1-color}% + \rule{\option{/fbox/@#1-box-width}}{\option{/fbox/@#1-box-height}}% + \hss + }% + \vss + }% + }% + \fi +} + +\newrobustcmd*\fbox@render{% + \begingroup + \fbox@setdim + %\typeout{render: height:\the\dimexpr\option{/fbox/@content-box-height}, lower=\the\dimexpr\option{/fbox/@lower}}% + \hbox{% + \fbox@kern{h}{/fbox/margin-left}% + \option{/fbox/render-insert-before}% + \lower \option{/fbox/@lower}% + \vbox{\offinterlineskip + \fbox@kern{v}{/fbox/margin-\fbox@top}% + \ifnum\option{/fbox/background-clip/@ord}=0\relax\fbox@plain@bgcolor{border}\fi + \fbox@border@pict% + \fbox@border@plain{\fbox@top}{h}% + \hbox{% + \fbox@border@plain{left}{v}% + \ifnum\option{/fbox/background-clip/@ord}=1\relax\fbox@plain@bgcolor{padding}\fi + \fbox@kern[/fbox/@padding-box-depth]{h}{/fbox/padding-left}% + \vbox{\offinterlineskip + \fbox@kern[/fbox/@content-box-width]{v}{/fbox/padding-\fbox@top}% + \ifnum\option{/fbox/background-clip/@ord}=2\relax\fbox@plain@bgcolor{content}\fi + \kern \option{/fbox/@content-box-height}% + \hrule height \z@ width \option{/fbox/@content-box-width}\relax + \fbox@kern[/fbox/@content-box-width]{v}{/fbox/padding-\fbox@bottom}% + }% + \fbox@kern[/fbox/@padding-box-depth]{h}{/fbox/padding-right}% + \fbox@border@plain{right}{v}% + }% + \fbox@border@plain{\fbox@bottom}{h}% + \fbox@border@pict@after% + \fbox@kern{v}{/fbox/margin-\fbox@bottom}% + }% + \option{/fbox/render-insert-after}% + \fbox@kern{h}{/fbox/margin-right}% + }% + \endgroup +} + +\options{% + /fbox/.new family = {/longbox}, +} +\options{/fbox, + % compatability + sep/.new style = {/fbox/padding=#1}, + rule/.new style = {/fbox/border-width=#1}, + % styles + margin/.new sides, + padding/.new sides, + border-width/.new sides = {/fbox/border-top-width=#1,/fbox/border-right-width=#2,% + /fbox/border-bottom-width=#3,/fbox/border-left-width=#4,% + /fbox/border-break-top-width=#1,/fbox/border-break-bottom-width=#3}, + border-color/.new sides = {/fbox/border-top-color=#1,/fbox/border-right-color=#2,% + /fbox/border-bottom-color=#3,/fbox/border-left-color=#4,% + /fbox/border-break-top-color=#1,/fbox/border-break-bottom-color=#3}, + border-style/.new sides = {/fbox/border-top-style=#1,/fbox/border-right-style=#2,% + /fbox/border-bottom-style=#3,/fbox/border-left-style=#4}, + border-break-style/.new style = {/fbox/border-break-top-style=#1,/fbox/border-break-bottom-style=#1}, + border-break-width/.new style = {/fbox/border-break-top-width=#1,/fbox/border-break-bottom-width=#1}, + border-break-color/.new style = {/fbox/border-break-top-color=#1,/fbox/border-break-bottom-color=#1}, + padding-break/.new style = {/fbox/padding-break-top=#1,/fbox/padding-break-bottom=#1}, + margin-break/.new style = {/fbox/margin-break-top=#1,/fbox/margin-break-bottom=#1}, + % background + background-clip/.new choice={border-box,padding-box,content-box}, + background-color/.new color = {}, + background-padding-color/.new color expr = \option{/fbox/background-color}, + background-border-color/.new color expr = \option{/fbox/background-color}, + background-content-color/.new color expr = \option{/fbox/background-color}, + % various + show-markers/.new toggle, + marker-color/.new color = gray, + marker-width/.new dim = 0.1pt, + render/.new choice = {default, plain, picture}, + render-insert-before/.new value, + render-insert-after/.new value, + plain-side-insert-before/.new value, + plain-side-insert-after/.new value, + picture-insert-before/.new value, + picture-insert-after/.new value, + picture-side-insert-before/.new value, + picture-side-insert-after/.new value, + % scoped (init) keys; these are reinitialized for nested scopes. + padding-top/.new length = {\fboxsep}, + padding-right/.new length = {\fboxsep}, + padding-bottom/.new length = {\fboxsep}, + padding-left/.new length = {\fboxsep}, + padding-break-top/.new length = {2pt}, + padding-break-bottom/.new length = {2pt}, + margin-top/.new length, + margin-right/.new length, + margin-bottom/.new length, + margin-left/.new length, + margin-break-top/.new length, + margin-break-bottom/.new length, + % borders: width + border-top-width/.new length = {\fboxrule}, + border-right-width/.new length = {\fboxrule}, + border-bottom-width/.new length = {\fboxrule}, + border-left-width/.new length = {\fboxrule}, + border-break-top-width/.new length = {\fboxrule}, + border-break-bottom-width/.new length = {\fboxrule}, + % borders: color + border-top-color/.new color = {.}, + border-right-color/.new color = {.}, + border-bottom-color/.new color = {.}, + border-break-top-color/.new color = {.}, + border-break-bottom-color/.new color = {.}, + border-left-color/.new color = {.}, + border-dark-mix/.new value = {!70!black}, + % borders: style + border-top-style/.new value=solid, + border-right-style/.new value=solid, + border-bottom-style/.new value=solid, + border-left-style/.new value=solid, + border-break-top-style/.new value=none, + border-break-bottom-style/.new value=none, + % corner radius + border-radius/.new cmd tuple = \optionsalso{ + /fbox/border-top-left-radius={#1,#2},/fbox/border-top-right-radius={#1,#2}, + /fbox/border-bottom-left-radius={#1,#2}, /fbox/border-bottom-right-radius={#1,#2}}, + border-top-left-radius/.new cmd tuple + = \optionsalso{/fbox/@border-top-left-radius-x=#1,/fbox/@border-top-left-radius-y=#2}, + border-top-right-radius/.new cmd tuple + = \optionsalso{/fbox/@border-top-right-radius-x=#1,/fbox/@border-top-right-radius-y=#2}, + border-bottom-left-radius/.new cmd tuple + = \optionsalso{/fbox/@border-bottom-left-radius-x=#1,/fbox/@border-bottom-left-radius-y=#2}, + border-bottom-right-radius/.new cmd tuple + = \optionsalso{/fbox/@border-bottom-right-radius-x=#1,/fbox/@border-bottom-right-radius-y=#2}, + % dashes and dots + border-dash/.new sides = {/fbox/border-top-dash=#1,/fbox/border-right-dash=#2,% + /fbox/border-bottom-dash=#3,/fbox/border-left-dash=#4,% + /fbox/border-break-top-dash=#1,/fbox/border-break-bottom-dash=#3}, + border-dashskip/.new sides= {/fbox/border-top-dashskip=#1,/fbox/border-right-dashskip=#2,% + /fbox/border-bottom-dashskip=#3,/fbox/border-left-dashskip=#4,% + /fbox/border-break-top-dashskip=#1,/fbox/border-break-bottom-dashskip=#3}, + border-dotskip/.new sides= {/fbox/border-top-dotskip=#1,/fbox/border-right-dotskip=#2,% + /fbox/border-bottom-dotskip=#3,/fbox/border-left-dotskip=#4,% + /fbox/border-break-top-dotskip=#1,/fbox/border-break-bottom-dotskip=#3}, + border-top-dash/.new dim = 0.6ex,%3\option{/fbox/border-top-width}, + border-bottom-dash/.new dim = 0.6ex,%3\option{/fbox/border-bottom-width}, + border-left-dash/.new dim = 0.6ex,%3\option{/fbox/border-left-width}, + border-right-dash/.new dim = 0.6ex,%3\option{/fbox/border-right-width}, + border-break-top-dash/.new dim = \option{/fbox/border-top-dash}, + border-break-bottom-dash/.new dim = \option{/fbox/border-bottom-dash}, + border-top-dashskip/.new dim = 0.7\option{/fbox/border-top-dash}, + border-bottom-dashskip/.new dim = 0.7\option{/fbox/border-bottom-dash}, + border-left-dashskip/.new dim = 0.7\option{/fbox/border-left-dash}, + border-right-dashskip/.new dim = 0.7\option{/fbox/border-right-dash}, + border-break-top-dashskip/.new dim = \option{/fbox/border-top-dashskip}, + border-break-bottom-dashskip/.new dim = \option{/fbox/border-bottom-dashskip}, + border-top-dotskip/.new dim = 2\option{/fbox/border-top-width}, + border-bottom-dotskip/.new dim = 2\option{/fbox/border-bottom-width}, + border-left-dotskip/.new dim = 2\option{/fbox/border-left-width}, + border-right-dotskip/.new dim = 2\option{/fbox/border-right-width}, + border-break-top-dotskip/.new dim = \option{/fbox/border-top-dotskip}, + border-break-bottom-dotskip/.new dim = \option{/fbox/border-bottom-dotskip}, + % computed + @lower/.new length, + @content-box-width/.new dim = \option{/longbox/@content-box-width}, + @content-box-height/.new dim = \option{/longbox/@content-box-height}, + @content-box-depth/.new dim = \option{/longbox/@content-box-depth}, + @padding-box-height/.new length, + @padding-box-depth/.new length, + @padding-box-width/.new length, + @border-box-width/.new length, + @border-box-height/.new length, + @border-box-depth/.new length, + % computed: not for the user + @border-top-left-radius-x/.new length, + @border-top-right-radius-x/.new length, + @border-bottom-left-radius-x/.new length, + @border-bottom-right-radius-x/.new length, + @border-top-left-radius-y/.new length, + @border-top-right-radius-y/.new length, + @border-bottom-left-radius-y/.new length, + @border-bottom-right-radius-y/.new length, + % computed inner radius; zero if border radius center is inside the borders + @border-top-left-iradius-x/.new dim, + @border-top-right-iradius-x/.new dim, + @border-bottom-left-iradius-x/.new dim, + @border-bottom-right-iradius-x/.new dim, + @border-top-left-iradius-y/.new dim, + @border-top-right-iradius-y/.new dim, + @border-bottom-left-iradius-y/.new dim, + @border-bottom-right-iradius-y/.new dim, + % computed inner corner coordinates (center of inner-radius) (where 0,0 is bottom-left) + @border-top-left-ix/.new length, + @border-top-left-iy/.new length, + @border-top-right-ix/.new length, + @border-top-right-iy/.new length, + @border-bottom-left-ix/.new length, + @border-bottom-left-iy/.new length, + @border-bottom-right-ix/.new length, + @border-bottom-right-iy/.new length, + % computed corner division angle + @border-top-left-phi/.new length, + @border-top-right-phi/.new length, + @border-bottom-left-phi/.new length, + @border-bottom-right-phi/.new length, + % computed various + @side/.new choice = {top,right,bottom,left,break-bottom,break-top}, + @side-horizontal/.new toggle, +} + +\newcommand\fbox@adjustoptions{% + %\typeout{ regular fbox adjustoptions}% + % set width of borders with style none to 0 + \def\do##1{% + \ifoptionequal{/fbox/border-##1-style}{hidden}{\option@invoke{/fbox/border-##1-style}{none}}{}% + \ifoptionequal{/fbox/border-##1-style}{none}{% + \options{/fbox/border-##1-width=0pt}% + }{}% + }% + \docsvlist{top,right,bottom,left,break-bottom,break-top}% + \options{% + /longbox/skip-left= + \option{/fbox/border-left-width} + \option{/fbox/padding-left} + \option{/fbox/margin-left}, + /longbox/skip-right= + \option{/fbox/border-right-width} + \option{/fbox/padding-right} + \option{/fbox/margin-right}, + /longbox/skip-top= + \option{/fbox/border-top-width} + \option{/fbox/padding-top} + \option{/fbox/margin-top}, + /longbox/skip-bottom= + \option{/fbox/border-bottom-width}+\option{/fbox/padding-bottom}+\option{/fbox/margin-bottom}, + /longbox/skip-break-top= + \option{/fbox/border-break-top-width} + \option{/fbox/padding-break-top} + \option{/fbox/margin-break-top}, + /longbox/skip-break-bottom= + \option{/fbox/border-break-bottom-width}+\option{/fbox/padding-break-bottom}+\option{/fbox/margin-break-bottom}, + }% + \longbox@adjustoptions% +} + +\newenvironment{longfbox}[1][]{% + \begin{longbox@env}{/fbox}{/longbox/render={\protect\fbox@render},/longbox/adjust-options={\protect\fbox@adjustoptions},#1}% +}{\end{longbox@env}} + +\newcommand\lfbox[2][]{% + \begingroup + \longbox@cmd{/fbox}{/longbox/render={\protect\fbox@render},/longbox/adjust-options={\protect\fbox@adjustoptions},#1}{#2}% + \endgroup +} + +\newcommand*\newfboxstyle[2]{% + \options{/fbox,#1/.new style* = {#2}}% +} + +\newfboxstyle{rounded}{border-radius=1ex} +\newfboxstyle{tight}{padding=0pt,margin=0pt,baseline-skip=false} +\newfboxstyle{dotted}{border-width=0.8pt,border-style=dotted} + +\newcommand*\fboxset[1]{% + \options{/fbox,#1}% +}
\ No newline at end of file |