# Baker's percentage symbol -- % in a loaf using TikZ

First, a little background.

Professional bakers (and, increasingly, bread baking enthusuasts generally as well) always weigh everything, particularly flour which is a highly variable substance: a cup (a volume measure) may weigh anything from a little over 3 ounces to a bit less than 5 ounces depending on how it is measured. It has become common for recipes using flour (bread, pastry) to specify ingredients by weight and baker's percentages. A baker's percentage (BP) is the percentage of the weight of a particular ingredient and the weight of the flour. Modernist Bread (https://modernistbread.com) employs a useful notation for BP:

Uses can be found in recipe tables at (https://modernistcuisineshop.com/products/modernist-bread-at-home), of which the following is an excerpt:

This also shows the utility of the BP symbol as apposed to the usual % symbol. (For what it's worth, one of the many uses of BP is the percentage of liquid's weight relative to the weight of the flour: This gives an immediate indication of how sticky, or not, the dough will be -- important indication of the manner in which the dough will be handled and the texture of the finished product. In this case 63.79, indicating a relatively tight, non-sticky dough.)

To create the loaf shape, I started with the following skeleton:

Then applied instances of [in=...,out=...]:

Close, but there are two problems: 1) a tiny disconnect at D and 2) a subtle dimple at F:

Clearly, there are some aspects of [in=...,out=...] that I don't understand. Thanks in advance for any insights

All of the above was generated with:

\documentclass[12pt]{article}

\usepackage[%showframe,
papersize={5.5in,8.5in},margin=0.6in]{geometry}
\usepackage{fontspec,tikz}

\newsavebox{\bpbox}

\newlength{\loafdomeht}
\newlength{\loafsideht}
\newlength{\puffht}
\newlength{\loafhalfwd}

\def\sideslope{97}% angles BAI HIA
\def\myloose{0.75}
\def\domeangle{30}% angle between CD and DE; between EF and FG

\setmainfont{STIX Two Text}
\parindent0pt

\begin{document}

\thispagestyle{empty}

\setlength{\loafdomeht}{0.075in}% height above D--F
\setlength{\loafsideht}{0.5in}%% AB=HI
\setlength{\puffht}{0.1in}% =BC=CD=FG=GH
\setlength{\loafhalfwd}{0.325in}%=0.5AI

The skeleton:

\tikz[baseline,every node/.style={font=\tiny}]{%
\draw (0,0)node[left]{A}
-- ++(\sideslope:\loafsideht)node[left]{B}
-- ++(-\puffht,\puffht)node[left]{C}
-- ++(\puffht,\puffht)node[left]{D}
-- ++(\loafhalfwd,\loafdomeht)node[above]{E}
-- ++(\loafhalfwd,-\loafdomeht)node[right]{F}
-- ++(\puffht,-\puffht)node[right]{G}
-- ++(-\puffht,-\puffht)node[right]{H}
-- ++(-\sideslope:\loafsideht)node[right]{I}
-- cycle;
}

\bigskip

Thickened and rounded:

\smallskip

\tikz[baseline]{%
\draw[line width=2pt] (0,0)
-- ++(\sideslope:\loafsideht)to[out=160,in=270]
++(-\puffht,\puffht) to[in=\domeangle,out=90]
++(\puffht,\puffht)to[in=180,out=\domeangle,looseness=\myloose]
++(\loafhalfwd,\loafdomeht)to[out=0,in={180-\domeangle},looseness=\myloose]
++(\loafhalfwd,-\loafdomeht)to[out=-\domeangle,in=90]
++(\puffht,-\puffht)to[out=270,in=30]
++(-\puffht,-\puffht)[rounded corners=0.2em]
-- ++(-\sideslope:\loafsideht)
-- cycle;
}

\bigskip

The problems:

\tikz[baseline]{%
\draw[line width=2pt] (0,0)
-- ++(\sideslope:\loafsideht)to[out=160,in=270]
++(-\puffht,\puffht) to[in=\domeangle,out=90]
++(\puffht,\puffht)node[draw,circle,red]{}to[in=180,out=\domeangle,looseness=\myloose]
++(\loafhalfwd,\loafdomeht)to[out=0,in={180-\domeangle},looseness=\myloose]
++(\loafhalfwd,-\loafdomeht)node[circle,draw,blue]{}to[out=-\domeangle,in=90]
++(\puffht,-\puffht)to[out=270,in=30]
++(-\puffht,-\puffht)[rounded corners=0.2em]
-- ++(-\sideslope:\loafsideht)
-- cycle;
}

\sbox{\bpbox}{% for repeated use in text, changing inches to ems:
\setlength{\loafdomeht}{0.075em}%
\setlength{\loafsideht}{0.5em}%
\setlength{\puffht}{0.1em}%
\setlength{\loafhalfwd}{0.325em}%
\tikz[outer sep=0pt,inner sep=0pt]{%
\draw[line width=0.04em] (0,0)coordinate(A)
-- ++(\sideslope:\loafsideht)to[out=150,in=270]
++(-\puffht,\puffht) to[in=\domeangle,out=90]
++(\puffht,\puffht)to[in=180,out=\domeangle,looseness=\myloose]
++(\loafhalfwd,\loafdomeht)to[out=0,in={180-\domeangle},looseness=\myloose]coordinate(E)
++(\loafhalfwd,-\loafdomeht)to[out=-\domeangle,in=90]
++(\puffht,-\puffht)to[out=270,in=30]
++(-\puffht,-\puffht)[rounded corners=0.075em]
-- ++(-\sideslope:\loafsideht)coordinate(I)
-- cycle;
\node[font=\scriptsize] at (current bounding box.center) {\%};
}%
}%
\NewDocumentCommand{\bp}{}{\usebox{\bpbox}}

\begingroup
\small
\begin{tabular}{llll}
INGREDIENTS& WEIGHT& VOLUME& \bp\\\hline
High-gluten flour*&250\thinspace &2 cups&100\\
Butter, cold&145\thinspace g&⅔ cup&50\\
$\cdots$\\
Eggs, cold&120\thinspace g& 2 ea&41.38\\
Whole milk, cold&65\thinspace g&¼ cup& 22.41\\\hline
\end{tabular}
\endgroup

\end{document}


# Update

As I mentioned in a comment, @daleif had mentioned Bézier curves and that prompted me to wonder if the Hobby tikzlibrary could be used. Though this is the very first time I have used it, it appears to do the trick very nicely indeed:

\documentclass[12pt]{article}

\usepackage[%showframe,
papersize={5.5in,8.5in},margin=0.6in]{geometry}
\usepackage{fontspec,tikz}
\usetikzlibrary{calc,positioning,hobby}

\newsavebox{\bpbox}

\newlength{\loafdomeht}
\newlength{\loafsideht}
\newlength{\puffht}
\newlength{\loafhalfwd}

\def\sideslope{97}% angles BAI HIA

\setmainfont{STIX Two Text}
\parindent0pt

\begin{document}

\thispagestyle{empty}

\setlength{\loafdomeht}{0.075in}% height above D--F
\setlength{\loafsideht}{0.5in}%% AB=HI
\setlength{\puffht}{0.1in}% =BC=CD=FG=GH
\setlength{\loafhalfwd}{0.325in}%=0.5AI

\tikz[baseline,use Hobby shortcut]{%
%% set the drawing points
\path (0,0)coordinate(A)
-- ++(\sideslope:\loafsideht)coordinate(B)
-- ++(-\puffht,\puffht)coordinate(C)
-- ++(\puffht,\puffht)coordinate(D)
-- ++(\loafhalfwd,\loafdomeht)coordinate(E)
-- ++(\loafhalfwd,-\loafdomeht)coordinate(F)
-- ++(\puffht,-\puffht)coordinate(G)
-- ++(-\puffht,-\puffht)coordinate(H)
-- ++(-\sideslope:\loafsideht)coordinate(I)
-- cycle;
\coordinate (M) at ($(A)!0.5!(I)$);% find the middle of the loaf
\coordinate (X) at (M |- E);% locate the dome top middle
\draw (A) -- (B) .. (C) .. (D) .. (X) .. (F) .. (G) .. (H) -- (I) -- cycle;
}

%% Notice the use of **em** units for lengths: this ensures that if the font size is changed
%% the symbol will still look as it should relative to surrounding text.
\sbox{\bpbox}{% for repeated use in text, changing inches to ems:
\setlength{\loafdomeht}{0.075em}%
\setlength{\loafsideht}{0.5em}%
\setlength{\puffht}{0.1em}%
\setlength{\loafhalfwd}{0.325em}%
\tikz[outer sep=0pt,inner sep=0pt,use Hobby shortcut]{%
\path (0,0)coordinate(A)
-- ++(\sideslope:\loafsideht)coordinate(B)
-- ++(-\puffht,\puffht)coordinate(C)
-- ++(\puffht,\puffht)coordinate(D)
-- ++(\loafhalfwd,\loafdomeht)coordinate(E)
-- ++(\loafhalfwd,-\loafdomeht)coordinate(F)
-- ++(\puffht,-\puffht)coordinate(G)
-- ++(-\puffht,-\puffht)coordinate(H)
-- ++(-\sideslope:\loafsideht)coordinate(I)
-- cycle;
\coordinate (M) at ($(A)!0.5!(I)$);% find the middle of the loaf
\coordinate (X) at (M |- E);% locate the dome top middle
\draw (A) -- (B) .. (C) .. (D) .. (X) .. (F) .. (G) .. (H) -- (I) -- cycle;
\node[font=\scriptsize] at (current bounding box.center) {\%};
}%
}%
\NewDocumentCommand{\bp}{}{\usebox{\bpbox}}

\begingroup
\small
\begin{tabular}{llll}
INGREDIENTS& WEIGHT& VOLUME& \bp\\\hline
High-gluten flour*&290\thinspace &2 cups&100\\
Butter, cold&145\thinspace g&⅔ cup&50\\
$\cdots$\\
Eggs, cold&120\thinspace g& 2 ea&41.38\\
Whole milk, cold&65\thinspace g&¼ cup& 22.41\\\hline
\end{tabular}
\endgroup

\end{document}


# Update 2

Just a note to demonstrate the advantages of using font-based measurements (the em) in constructing grraphics intended to be used in text. Though the Hobby curves impose a computation penalty, the symbol is generally not used frequently so can be regenerated afresh each time it is used.

One change here: The width of the loaf is now dependent on the width of the % character.

\documentclass[]{article}

\usepackage[%showframe,
papersize={5.5in,8.5in},margin=0.6in]{geometry}
\usepackage{fontspec,tikz}
\usetikzlibrary{calc,positioning,hobby}

\newsavebox{\bpbox}

\newlength{\loafdomeht}
\newlength{\loafsideht}
\newlength{\puffht}
\newlength{\loafhalfwd}

\def\sideslope{97}% angles BAI HIA

%% Notice the use of **em** units for lengths: this ensures that if the document
%% font size is changed the symbol will still look as it should relative to surrounding text.
\NewDocumentCommand{\bp}{s o}{% *=?; #2=?; Tweak any or all of the following to suit:
\setlength{\loafdomeht}{0.065em}%
\setlength{\loafsideht}{0.45em}%
\setlength{\puffht}{0.125em}%
\setbox0=\hbox{\fontsize{0.7em}{0.7em}\selectfont\%}% <--scriptfont size relative to current>
\setlength{\loafhalfwd}{0.7\wd0}%
\smash{%
\tikz[outer sep=0pt,inner sep=0pt,use Hobby shortcut]{%
\path (0,0)coordinate(A)
-- ++(\sideslope:\loafsideht)coordinate(B)
-- ++(-\puffht,\puffht)coordinate(C)
-- ++(\puffht,\puffht)coordinate(D)
-- ++(\loafhalfwd,\loafdomeht)coordinate(E)
-- ++(\loafhalfwd,-\loafdomeht)coordinate(F)
-- ++(\puffht,-\puffht)coordinate(G)
-- ++(-\puffht,-\puffht)coordinate(H)
-- ++(-\sideslope:\loafsideht)coordinate(I)
-- cycle;
\coordinate (M) at ($(A)!0.5!(I)$);% find the middle of the loaf
\coordinate (X) at (M |- E);% locate the dome top middle
\draw[line width=0.04em] (A) -- (B) .. (C) .. (D) .. (X) ..
(F) .. (G) .. (H) -- (I) -- cycle;
\node[font=\scriptsize] at ($(X)!0.5!(M)$) {\box0};
}%
}%
}%

\setmainfont{STIX Two Text}
\parindent0pt

\begin{document}

\thispagestyle{empty}

\foreach \S in {tiny,scriptsize,footnotesize,small,normalsize,large,Large,LARGE,huge,Huge}{%
\S: \begingroup\csname \S \endcsname\bp\par\endgroup
}

\bigskip

\begin{minipage}{\textwidth}
This is a bunch of bla bla bla to take up a certain amount of useless space.
This is some text X\,\bp\,X\ with a symbol in it.\footnote{A symbol \bp\ in a footnote: Note that the symbol has scaled with the prevailing font size in this footnote.}
This is a bunch of bla bla bla to take up a certain amount of useless space.
This is a bunch of bla bla bla to take up a certain amount of useless space.
\end{minipage}%

\end{document}


# Followup

Taking a suggestion from @MS-SPO and @daleif, I have omitted the points D and F (see original “skeleton”) -- this has necessitated a revision of some of the definitions. This has also made the routine quicker.

Use \bpsetup[<keyval options>] to change several drawing parameters; \bpsetup[bpnoisy] will write to the log file what is happening each time \bp is used. The \bp macro is now a bit smarter -- if the symbol has been previously created, it is used; \bp* forces regeneration -- useful if the font and/or size has changed; \bp[<stuff>] adds stuff to the log file for that use of \bp.

\documentclass[]{article}
%quick Hobby shortcut: sizes < \normalsize gives bad shapes; \tiny gives division by 0 error; + Drop 'D' and 'F' from \draw, though not from the skeleton -- requires fiddling with basic lengths
\usepackage[%showframe,
papersize={5.5in,8.5in},margin=0.6in]{geometry}
\usepackage{fontspec,tikz,keyval,multicol}
\usetikzlibrary{calc,positioning,hobby}

\newsavebox{\bpbox}

\newlength{\loafdomeht}
\newlength{\loafsideht}
\newlength{\puffht}
\newlength{\loafhalfwd}
\newif\ifbpnoisy
%% tweak any or all to suit:
\def\pcscale{0.7}
\def\loafwdscale{0.525}
\def\loafsidescale{0.375}
\def\linewidthscale{0.04}

\def\sideslope{97}% angles BAI HIA

\makeatletter
\define@key{bpsymb}{pcscale}{\def\pcscale{#1}}% about 0.7 (of em) (of em, ≈scriptfontsize)
\define@key{bpsymb}{bpnoisy}[true]{\csname bpnoisy#1\endcsname}
\makeatother

%% Notice the use of **em** units for lengths: this ensures that if the document
%% font size is changed the symbol will still look as it should relative to surrounding text.
\NewDocumentCommand{\bpsetup}{O{}}{%
\setkeys{bpsymb}{#1}%
}

\NewDocumentCommand{\mksymb}{}{% Minus two points; Tweak any or all of the following to suit:
\setlength{\loafdomeht}{0.25em}%
\setlength{\loafsideht}{\loafsidescale em}%
\setlength{\puffht}{0.15em}%
\setbox0=\hbox{\normalfont\fontsize{\pcscale em}{\pcscale em}\selectfont\%}%
\setlength{\loafhalfwd}{\loafwdscale\wd0}%
\sbox{\bpbox}{%
\smash{%
\tikz[outer sep=0pt,inner sep=0pt,use Hobby shortcut]{%
\path
(0,0)coordinate(A)
-- ++(\sideslope:\loafsideht)coordinate(B)
-- ++(180-45:\puffht)coordinate(C)
(2*\loafhalfwd,0)coordinate(I)
-- ++(180-\sideslope:\loafsideht)coordinate(H)
-- ++(45:\puffht)coordinate(G);
\coordinate (M) at ($(A)!0.5!(I)$);
\coordinate (X) at ([yshift=\loafdomeht]M |- G);
\draw[line width=\linewidthscale em] (A) -- (B) .. (C) .. (X) ..
(G) .. (H) -- (I) -- cycle; % draw the loaf
\node[] at ($(X)!0.5!(M)$) {\box0};% add the \%
}%
}%
}%
}

\NewDocumentCommand{\bp}{s o}{% *=force regenerate; #2=[text to appear in \typeout]
\IfBooleanTF{#1}%
{\ifbpnoisy\typeout{force generating new\IfNoValueF{#2}{, #2}}\fi\mksymb}%
{\ifvoid\bpbox% no previous instance, make new
\ifbpnoisy\typeout{is void, generating new\IfNoValueF{#2}{, #2}}\fi\mksymb
\fi}%
\usebox{\bpbox}%
}%

\setmainfont{STIX Two Text}
\parindent0pt

\title{BP Symbol \bp*[title]\ Test}
\author{S. G. Moye}

\begin{document}

\bpsetup[bpnoisy=true]

\maketitle

\thispagestyle{empty}

\section{BP symbol \bp*\ for use in recipes \& tables }

\begin{multicols}{2}
\foreach \S in {%
tiny, % tiny gives error, division by 0, using quick Hobby shortcut
scriptsize,
footnotesize,small,
normalsize,large,Large,LARGE,huge,Huge}{%
\S: \begingroup\csname\S\endcsname\bp*\par\endgroup
}
\columnbreak
New skeleton:

\begingroup
\setlength{\loafdomeht}{0.1in}% height above D--F
\setlength{\loafsideht}{0.5in}%% AB=HI
\setlength{\puffht}{0.1in}% =BC=CD=FG=GH
\setlength{\loafhalfwd}{0.225in}%=0.5AI

\tikz[baseline,every node/.style={font=\tiny}]{%
\path
(0,0)coordinate(A)node[left]{A}
-- ++(\sideslope:\loafsideht)coordinate(B)node[left]{B}
-- ++(135:\puffht)coordinate(C)node[left]{C}
(2*\loafhalfwd,0)coordinate(I)node[right]{I}
-- ++(180-\sideslope:\loafsideht)coordinate(H)node[right]{H}
-- ++(45:\puffht)coordinate(G)node[right]{G};
\coordinate (M) at ($(A)!0.5!(I)$);
\coordinate (X) at ([yshift=\loafdomeht]M |- G);
%
\draw (A) -- (B) -- (C) -- (X) -- (G) -- (H) -- (I) -- cycle;
\node at (M) {M};
\node at (X) {X};
}
\endgroup
\end{multicols}

This is a test \bp[start]
\bigskip

\begin{minipage}{\textwidth}
This is a bunch X\bp X of bla bla bla to take up a certain amount of useless space. This is some text XO\bp OX with a symbol in it.\footnote{A BP symbol \bp*[fn]\ in a footnote, and this is another \bp[fn2]: Note that the symbol has been scaled to match the prevailing font size for footnotes. Also note the first use in the footnote: \texttt{\string\bp*} to force rescaling.} This is \bp\ a bunch of bla bla bla to take up a certain amount of useless space. This is in contrast to saying, for example, that a given flour has 14\% protein. This is a bunch \bp\ of bla bla bla to take up a certain amount of useless space.
\end{minipage}%

\bigskip

\begingroup
\footnotesize
\begin{tabular}{llll}
INGREDIENTS& WEIGHT& VOLUME& \bp*\\\hline
High-gluten flour*&290\,g&2 cups&100\\
Butter, cold&145\,g&⅔ cup&50\\
$\cdots$\\
Eggs, cold&120\,g& 2 ea&41.38\\
Whole milk, cold&65\,g&¼ cup& 22.41\\\hline
\end{tabular}
\endgroup

\end{document}


• I woule probably drop D and F and use bezier curves and polar coord on the support points instead Commented May 23 at 12:52
• The fontawesome5 package contains a bread-slice symbol. It is a filled symbol, but maybe you can overlay the % in white over it. Commented May 23 at 13:08
• B and D, and symm., are obsolte: in and out will do. // 0deg is right, or east. If you go in=30deg, go out=150 (180-30). // At C you want inout angles of 90/270. // It may suffice to use A, B and E only. // Bezier have a wider range, but also are harder to visualize before compile and need more space in standalone. Commented May 23 at 13:12
• unrelated to your actual question but why is 145g of butter 50 BP of 250g of flour? I must be missing something:-) Commented May 23 at 16:28
• @DavidCarlisle Very sloppy of me. Thanks and corrected. Commented May 23 at 18:30

I simplified your loaf and then redefined your \bp command to take any TikZ options an optional argument. For example:

Here is your table and code:

\documentclass[12pt]{article}

\usepackage[papersize={5.5in,8.5in},margin=0.6in]{geometry}
\usepackage{fontspec,tikz}

\tikzset{
loaf/.style={
inner sep=5pt,
path picture={
\node[inner xsep=7pt, inner ysep=6.5pt](inbound) at (path picture bounding box){};
\draw[thick, looseness=.8, #1](inbound.30) to[out=90, in=0] (inbound.90)
to[out=180, in=90] (inbound.150) to[out=270, in=150] ++(2pt,-2pt)[rounded corners=1pt]
-- (inbound.240) -- (inbound.300)[sharp corners]
-- ([shift={(-2pt,-2pt)}]inbound.30) to[out=30, in=270] cycle;
}
},
loaf/.default={}
}

\newsavebox{\bpbox}

\setmainfont{STIX Two Text}
\parindent0pt

\begin{document}

\thispagestyle{empty}

\newcommand{\bp}[1][]{\tikz[baseline=(Loaf.text)]{\node[loaf={#1}](Loaf){\%}}}

\begingroup
\small
\begin{tabular}{llll}
INGREDIENTS& WEIGHT& VOLUME& \bp[brown, fill=brown!20]\\\hline
High-gluten flour*&250\thinspace &2 cups&100\\
Butter, cold&145\thinspace g&⅔ cup&50\\
$\cdots$\\
Eggs, cold&120\thinspace g& 2 ea&41.38\\
Whole milk, cold&65\thinspace g&¼ cup& 22.41\\\hline
\end{tabular}
\endgroup

\end{document}


How about this simple code (uses pure pdfLaTeX)? I used an arc for the top loaf and enabled rounded corners for the bottom two corners. A tiny percent sign is placed inside the loaf with tight boundaries (i.e. no inner sep or outer sep).

You might want to experiment with the scale; I eyeballed it so that the total height of the loaf is approximately the height of the font. To make things more precise, I smashed the symbol to height and depth zero and artificially gave the symbol the height and depth of the letter X.

\documentclass{article}

\usepackage{tikz}
\usepackage{booktabs}

\newcommand{\bp}{\smash{\tikz[scale=.15]{
[rounded corners=1pt] -- (-.6,-1.8) -- (.6,-1.8) [sharp corners] -- cycle;
\node[outer sep=0pt, inner sep=0pt] at (-90:1) {\tiny\%};
}}\vphantom{X}}

\begin{document}

\begin{table}
\begin{tabular}{@{}llll@{}} \toprule
INGREDIENTS & WEIGHT & VOLUME & \bp \\ \midrule
High-gluten flour* & 250\,g & 2\,cups & 100 \\
Butter, cold & 145\,g & 2/3\,cup & 50 \\
\dots \\
Eggs, cold & 120\,g & 2\,ea & 41.38 \\
Whole milk, cold & 65\,g & 1/4\,cup & 22.41 \\ \bottomrule
\end{tabular}\\

I also used the booktabs package, which seems like a good call for such use cases. The siunitx package might be worth a consideration, but honestly, the unit cup with plural cups is a bit difficult.