Unlimited size delimiters with TikZ

Compare this two outputs

Which one would you prefer to have in your document? I would definetly prefer the one on the right. However, most fonts (MinionPro in this case) only offer four sizes of delimiters available, and, in case one needs a bigger size they rely on the “extensible delimiters” which might not look as good.

Since we have TikZ available, I thought that it would be great to create some —flexible— options to enhace delimiters in TeX.

Question: How could one use the power of TikZ to create unlimitedly large delimiters?

I've already written some code to achieve that. However, I ask the question that way so that it's not closed because of OffTopic, or Too Broad, or even Unclear.

My idea was to create a certain figure in TikZ (inside a user command) which could be easy configurable by certain parameters. The most important one is the height, which is the mandatory argument to a hypothetical command \PARENS{height}{content}. I've already done many delimiters (just by hand, in less than two hours, so no effort has been put into that), but I will share here the parenthesis (at least for now). In my case there is no relation between one parameter and another (which could be perfect in an ideal solution)

However, I think my idea could be developed much more. Right now, they are just a tikzpicture for the opening delimiter and the same one for the closing (just with xscale=-1); in case one wants to automatically measure the height of the contents, I just set a box and measure it (which is slow when using nested parenthesis); I mix expl3 with TikZ, etc.

So, in case one wants to answer this question, these are some points that would be great to enhance

• May be using proper TikZ systems to offer even more flexibility (may be add the delimiters as some sort of pic or decoration);
• using TikZ systems to measure the height of the content;
• enable flexible calculation of parameters in function of the height;
• may be create a system to save all the created parenthesis to boxes and just reuse them when the same height is used;
• proper decision about what parameters are necessary and which not;
• etc.

Of course, different styles are also appreciated, and even different delimiters (I chose parenthesis for the example, since those are a bit more trickier than the rest, but, of course, nothing to do with braces!).

What I'm looking for is, apart from the answer to my question, any idea that would improve, in any way, the usability of this delimiters.

In any case, I will read comments / suggestions or whatever to improve the question in any possible way.

EDIT: This is not an easy question, and may not have answers. In any case, two things I came along in the last months.

• There's a calligraphy library for TikZ, it would be nice to have an answer with the parenthesis or delimiters provided by that library.
• May be, much more easier than my solution would be to create a function that takes in account every variable to determine two control points; these would be used in the end to create the curve.

Well, here it is the first step.

The code is a mess (mixing expl3 and TikZ is not a good idea, but is the knowledge I have). The TikZ code is even less legible because I used search and replace after writing it to substitute some things, I hope you (in case of interest) can read it.

I created a command \PARENS{…} which puts parenthesis around the content in a similar way than \DeclarePairedDelimiter. \PARENS*{…} automatically measures the height of the content (it's wrongly done, because there can be different heights over and under the line where everything is centered, but I leave that for later).

My \PARENS[config]{…} can be configurated by some parameters (it might be easier to try changing them so one can see how it works)

• height, which is the “important” parameter;
• outwidth, the width in the top and bottom of the parenthesis;
• midwidth, the width in the middle of the parenthesis;
• insep, space between the contents and the delimiters;
• outsep, distance between the delimiters and the outside of them;
• proportion, the relation between the height of the delimiters and the total horizontal space they use;
• outangle, the angle that forms at the extremes;
• inangle-i, inangle-ii, difficult to explain, usually next to perpendicular to outangle;
• looseness-i and looseness-ii, the parameters (between 0 and 1, IIRC) that control the curvature of the parenthesis (because ind the tikzpicture I use looseness to draw curved lines, which might not be perfect.

Moreover, I added 15 already configured parenthesis, to avoid using \PARENS*{…} which becomes quite slow, that can be used like \PARENS[15]{…}. They all resemble the 15 parenthesis offered by Typoma Minion Math. One could, of course, configure more by default to use in his document.

Here it's the long —and far from optimal— code

%!TEX TS-program = pdflatex
\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenx}
\usepackage{MinionPro}
\usepackage{mathtools,xparse,tikz}
\usetikzlibrary{calc}

\newcommand*\tikzangle[2]{#1:#2}
\ExplSyntaxOn
\keys_define:nn { delimiter }
{
paren .code:n = \keys_set:nn { delimiter / paren } {#1} ,
}
% PARENS (fold)
\dim_new:N \l_paren_height_dim
\dim_new:N \l_paren_outwidth_dim
\dim_new:N \l_paren_midwidth_dim
\dim_new:N \l_paren_insep_dim
\dim_new:N \l_paren_outsep_dim
\tl_new:N \l_paren_proportion_tl
\tl_new:N \l_paren_outangle_tl
\tl_new:N \l_paren_inangle_i_tl
\tl_new:N \l_paren_inangle_ii_tl
\tl_new:N \l_paren_looseness_i_tl
\tl_new:N \l_paren_looseness_ii_tl
\keys_define:nn { delimiter / paren }
{
height       .dim_set:N = \l_paren_height_dim      ,
outwidth     .dim_set:N = \l_paren_outwidth_dim    ,
midwidth     .dim_set:N = \l_paren_midwidth_dim    ,
insep        .dim_set:N = \l_paren_insep_dim       ,
outsep       .dim_set:N = \l_paren_outsep_dim      ,
proportion   .tl_set:N  = \l_paren_proportion_tl   ,
outangle     .tl_set:N  = \l_paren_outangle_tl     ,
inangle-i    .tl_set:N  = \l_paren_inangle_i_tl    ,
inangle-ii   .tl_set:N  = \l_paren_inangle_ii_tl   ,
looseness-i  .tl_set:N  = \l_paren_looseness_i_tl  ,
looseness-ii .tl_set:N  = \l_paren_looseness_ii_tl ,
height       .initial:n = 11pt                     ,
outwidth     .initial:n = .024cm                   ,
midwidth     .initial:n = .045cm                   ,
insep        .initial:n = .1em                     ,
outsep       .initial:n = .1em                     ,
proportion   .initial:n = .275                     ,
outangle     .initial:n = 43                       ,
inangle-i    .initial:n = 48                       ,
inangle-ii   .initial:n = 48                       ,
looseness-i  .initial:n = .8                       ,
looseness-ii .initial:n = .85                      ,
}
\NewDocumentCommand \PARENS { s o m }
{
\group_begin:
\IfBooleanT {#1}
{
\setbox0=\hbox{$\displaystyle#3$}
\dim_set:Nn \l_paren_height_dim { \ht0+\dp0 }
}
\IfValueT {#2} { \keys_set:nn { delimiter / paren } { #2 } }

\mathopen{
\kern \dim_use:N \l_paren_outsep_dim
\begin{tikzpicture}
[ xscale = -1,
baseline = \dim_eval:n { -\fontdimen22\textfont2 } ]
\coordinate (P1) at ( 0 , \dim_eval:n { .5\l_paren_height_dim } ) ;
\coordinate (P2) at ( $(P1) + ( \tikzangle { \l_paren_outangle_tl } { \l_paren_outwidth_dim } )$ ) ;
\coordinate (P3) at ( 0 , \dim_eval:n { -.5\l_paren_height_dim } ) ;
\coordinate (P4) at ( $(P3) + ( \tikzangle { -\l_paren_outangle_tl } { \l_paren_outwidth_dim } )$ ) ;
\coordinate (P5) at ( \dim_eval:n { \l_paren_proportion_tl\l_paren_height_dim/2 } , 0 ) ;
\coordinate (P6) at ( $(P5) + ( \tikzangle { 0 } { \l_paren_midwidth_dim } )$ ) ;
\fill [smooth]
(P1)
to
(P2)
to [ out = -\l_paren_inangle_ii_tl , in = 90 , looseness = \l_paren_looseness_ii_tl ]
(P6)
to [ out = -90 , in = \l_paren_inangle_ii_tl , looseness = \l_paren_looseness_ii_tl ]
(P4)
to (P3)
to [ out = \l_paren_inangle_i_tl , in = -90 , looseness = \l_paren_looseness_i_tl ]
(P5)
to [ out = 90 , in = -\l_paren_inangle_i_tl , looseness = \l_paren_looseness_i_tl ]
(P1)
to cycle
;
\end{tikzpicture}
\kern \dim_use:N \l_paren_insep_dim
}
#3
\mathclose{
\kern \dim_use:N \l_paren_insep_dim
\begin{tikzpicture}
[ baseline = \dim_eval:n { -\fontdimen22\textfont2 } ]
\coordinate (P1) at ( 0 , \dim_eval:n { .5\l_paren_height_dim } ) ;
\coordinate (P2) at ( $(P1) + ( \tikzangle { \l_paren_outangle_tl } { \l_paren_outwidth_dim } )$ ) ;
\coordinate (P3) at ( 0 , \dim_eval:n { -.5\l_paren_height_dim } ) ;
\coordinate (P4) at ( $(P3) + ( \tikzangle { -\l_paren_outangle_tl } { \l_paren_outwidth_dim } )$ ) ;
\coordinate (P5) at ( \dim_eval:n { \l_paren_proportion_tl\l_paren_height_dim/2 } , 0 ) ;
\coordinate (P6) at ( $(P5) + ( \tikzangle { 0 } { \l_paren_midwidth_dim } )$ ) ;
\fill [smooth]
(P1)
to
(P2)
to [ out = -\l_paren_inangle_ii_tl , in = 90 , looseness = \l_paren_looseness_ii_tl ]
(P6)
to [ out = -90 , in = \l_paren_inangle_ii_tl , looseness = \l_paren_looseness_ii_tl ]
(P4)
to (P3)
to [ out = \l_paren_inangle_i_tl , in = -90 , looseness = \l_paren_looseness_i_tl ]
(P5)
to [ out = 90 , in = -\l_paren_inangle_i_tl , looseness = \l_paren_looseness_i_tl ]
(P1)
to cycle
;
\end{tikzpicture}
\kern \dim_use:N \l_paren_outsep_dim
}
\group_end:
}
% (end)
\ExplSyntaxOff

\DeclarePairedDelimiter\pa{\lparen}{\rparen}

\ExplSyntaxOn
\keys_define:nn { delimiter / paren }
{
1 .meta:n =
{
height=9.16pt,
outangle=51,
inangle-i=38,
inangle-ii=33,
midwidth=.8pt,
outwidth=.33pt,
proportion=.379,
looseness-i=.81,
looseness-ii=.9,
insep=0pt,
outsep=0pt,
} ,
2 .meta:n =
{
height=11.28pt,
outangle=51,
inangle-i=41,
inangle-ii=35,
midwidth=.83pt,
outwidth=.35pt,
proportion=.357,
looseness-i=.82,
looseness-ii=.89,
insep=0pt,
outsep=0pt,
} ,
3 .meta:n =
{
height=14.44pt,
outangle=48,
inangle-i=43,
inangle-ii=37.7,
midwidth=.87pt,
outwidth=.38pt,
proportion=.336,
looseness-i=.81,
looseness-ii=.88,
insep=0pt,
outsep=0pt,
} ,
4 .meta:n =
{
height=17.6pt,
outangle=48,
inangle-i=45,
inangle-ii=40.5,
midwidth=.92pt,
outwidth=.4pt,
proportion=.322,
looseness-i=.81,
looseness-ii=.87,
insep=0pt,
outsep=0pt,
} ,
5 .meta:n =
{
height=20.74pt,
outangle=48,
inangle-i=46,
inangle-ii=41,
midwidth=.97pt,
outwidth=.42pt,
proportion=.312,
looseness-i=.81,
looseness-ii=.87,
insep=0pt,
outsep=0pt,
} ,
6 .meta:n =
{
height=23.92pt,
outangle=45,
inangle-i=46,
inangle-ii=43,
midwidth=.99pt,
outwidth=.46pt,
proportion=.308,
looseness-i=.8,
looseness-ii=.87,
insep=0pt,
outsep=0pt,
} ,
7 .meta:n =
{
height=27.02pt,
outangle=45,
inangle-i=47,
inangle-ii=44,
midwidth=1.04pt,
outwidth=.48pt,
proportion=.302,
looseness-i=.8,
looseness-ii=.87,
insep=0pt,
outsep=0pt,
} ,
8 .meta:n =
{
height=30.2pt,
outangle=46,
inangle-i=47,
inangle-ii=44,
midwidth=1.08pt,
outwidth=.51pt,
proportion=.297,
looseness-i=.796,
looseness-ii=.86,
insep=0pt,
outsep=0pt,
} ,
9 .meta:n =
{
height=33.38pt,
outangle=46,
inangle-i=47,
inangle-ii=45.2,
midwidth=1.13pt,
outwidth=.53pt,
proportion=.293,
looseness-i=.796,
looseness-ii=.86,
insep=0pt,
outsep=0pt,
} ,
10 .meta:n =
{
height=36.5pt,
outangle=46,
inangle-i=48,
inangle-ii=45.2,
midwidth=1.16pt,
outwidth=.56pt,
proportion=.291,
looseness-i=.796,
looseness-ii=.86,
insep=0pt,
outsep=0pt,
} ,
11 .meta:n =
{
height=42.92pt,
outangle=43.5,
inangle-i=48,
inangle-ii=46,
midwidth=1.16pt,
outwidth=.56pt,
proportion=.288,
looseness-i=.79,
looseness-ii=.86,
insep=0pt,
outsep=0pt,
} ,
12 .meta:n =
{
height=49.3pt,
outangle=43.5,
inangle-i=48,
inangle-ii=47,
midwidth=1.16pt,
outwidth=.56pt,
proportion=.286,
looseness-i=.795,
looseness-ii=.86,
insep=0pt,
outsep=0pt,
} ,
13 .meta:n =
{
height=55.68pt,
outangle=43.5,
inangle-i=48,
inangle-ii=47,
midwidth=1.16pt,
outwidth=.56pt,
proportion=.284,
looseness-i=.785,
looseness-ii=.85,
insep=0pt,
outsep=0pt,
} ,
14 .meta:n =
{
height=62.06pt,
outangle=43.5,
inangle-i=48,
inangle-ii=47,
midwidth=1.16pt,
outwidth=.56pt,
proportion=.283,
looseness-i=.79,
looseness-ii=.85,
insep=0pt,
outsep=0pt,
} ,
15 .meta:n =
{
height=68.44pt,
outangle=43.5,
inangle-i=48,
inangle-ii=48,
midwidth=1.15pt,
outwidth=.56pt,
proportion=.282,
looseness-i=.78,
looseness-ii=.85,
insep=0pt,
outsep=0pt,
} ,
}
\ExplSyntaxOff

\begin{document}
$\PARENS*{ \PARENS[15]{ \PARENS[14]{ \PARENS[13]{ \PARENS[12]{ \PARENS[11]{ \PARENS[10]{ \PARENS[9]{ \PARENS[8]{ \PARENS[7]{ \PARENS[6]{ \PARENS[5]{ \PARENS[4]{ \PARENS[3]{ \PARENS[2]{ \PARENS[1]{ x } } } } } } } } } } } } } } }^M }$
$\det\begin{pmatrix} a & b & c & d & e \\ a & b & c & d & e \\ a & b & c & d & e \end{pmatrix} \qquad \det\PARENS[10,outsep=2pt]{\begin{matrix} a & b & c & d & e \\ a & b & c & d & e \\ a & b & c & d & e \end{matrix}}$
\end{document}


What could be done better, I don't know! May be some sort of setting/using already saved boxes, may be not using looseness and using precalculated control points to draw bezier curves, may be using TikZ facilities to improve the robustness and fasten the compilation (pic or decoration?), etc. I don't know, anything would be welcome.

• Different delimiters need different parameters, for instance my \VERTS needs only: insep, outsep, width, height. – Manuel Aug 15 '14 at 12:30
• while your goal is desirable, the arcs for the taller parens are too pronounced. the added width not only leaves a very large gap at the middle of a tall matrix, it may force such a matrix to exceed the available page width, unnecessarily. the arcs would surely look better as arcs, but if you could aim for shallower arcs, that would be all to the good. test them out on one-column matrices, not as a series of nested parentheses. – barbara beeton Aug 15 '14 at 13:03
• That's the cool thing of it being configurable, that it can be easily changed. Even if I would love it to be more robust (so the parameters are functions themselves of the height which would mean that one needn't to change them), with my lousy code, in a matrix with 9 columns this \PARENS*[proportion=.12,inangle-i=72,inangle-ii=72,outangle=18,outwidth=.03cm] gives something acceptable. If you only change proportion you see why my code is not robust. EDIT: it's true that the arcs are too pronounced (but that doesn't matter in many cases), in those that matter, one could configure them. – Manuel Aug 15 '14 at 13:16
• @barbarabeeton Even more, it is absolutely easy to add another option to emulate that automatic enlarging (just adding a vertical rectangle in the middle). Which leaves us with exactly the same solution as traditional, say with \PARENS[venlarge=2cm]{…}, so 2 cm are just a vertical bar. – Manuel Aug 15 '14 at 14:42