3

I am trying to reproduce the following in Plain (Xe)TeX (with more oscillations if possible):

voltaire

That is to add a squiggle in the margin next to a given paragraph. I was thinking of the following API:

\beginsquiggle
Nos passions ne sont pas distinctes \&c.
\endsquiggle

Maybe one should use \sim and \cleaders,but \sim\mkern-3mu\sim is not a smooth join.

  • 1
    Welcome to TeX.SE! (Xe)TeX and friends are really cool, is there any chance you could make a small example of code with random text that people can play with ending with \bye please? Helps people help you if they can copy and paste, welcome and I hope you like it here! – JamesT Aug 30 '23 at 20:38
  • I would go with tikzpagenodes and tikzmark and put the squiggle between (current page text area) and (current page marginpar area). However, semirandom squiggles are very difficult to computerize. It might be easier to scale an image to fit. – John Kormylo Aug 30 '23 at 23:43
  • @JohnKormylo I would be more than happy with a repeating pattern –  Aug 31 '23 at 07:56

2 Answers2

5

Here is a possible solution. It won't work with page breaks, more work for that is needed...

\def\pdfliteral#1{\special{pdf:literal #1}}

\def\converttobp#1{\the\dimexpr .99626\dimexpr #1\relax\relax} % convert pt to bp \newdimen\squiggleosc \newdimen\squigglesep

\def\var#1#2{-\expandafter\\expanded{\converttobp{% \squiggleosc #1 + \squiggleosc #2/3}}} \def\ifneg#1{\ifodd #1 \empty\else -\fi \squigelamp} \def\squigglewidth{1} \def\gobble#1{} \def\secondoftwo#1#2{#2}

\def\varloop#1#2% {% \ifnum#1<#2 \ifneg{#1} \var{#1}{1} \ifneg{#1} \var{#1}{2} 0 \var{#1}{3} c \expandafter\secondoftwo \fi \gobble{\expandafter\varloop\expandafter{\the\numexpr#1+1}{#2}}% }

\newcount\squigglecount \def\squiggleline#1{\pdfliteral{q \squigglewidth w 1 j 1 J 0 0 m \varloop{0}{\the\numexpr #1\relax} S Q}}

\def\divceil#1#2{% \ifnum\numexpr #1 - #2*\numexpr #1/#2\relax>0 \the\numexpr #1/#2 +1\relax\else\the\numexpr #1/#2\relax\fi }

\def\squigglebox{% \raise .6\squiggleosc\hbox to0pt{\kern-\dimexpr \csname beg-x-\the\squigglecount\endcsname sp - \the\hoffset -1in +\squigglesep\relax \hbox{\squiggleline{% \numexpr\divceil{% (\csname beg-y-\the\squigglecount\endcsname - \csname end-y-\the\squigglecount\endcsname)}% {\numexpr\dimexpr\squiggleosc\relax\relax}+1\relax }}\hss}% }

\newlinechar=`^^J \newwrite\squigglefile \immediate\openin\squigglefile=squig.tex \ifeof\squigglefile \immediate\closein\squigglefile \else \immediate\closein\squigglefile\input squig \fi \immediate\openout\squigglefile=squig.tex

\def\beginsquiggle{\global\advance\squigglecount by 1 \ifcsname beg-x-\the\squigglecount\endcsname \ifvmode\noindent\leavevmode\pdfsavepos \squigglebox\hbox to\parindent{}% \else\pdfsavepos \squigglebox \fi\fi \write\squigglefile{ \unexpanded{\expandafter\def\csname} beg-x-\the\squigglecount\noexpand\endcsname {\the\pdflastxpos}^^J \unexpanded{\expandafter\def\csname} beg-y-\the\squigglecount\noexpand\endcsname {\the\pdflastypos} }% } \def\endsquiggle{\pdfsavepos \write\squigglefile{ \unexpanded{\expandafter\def\csname} end-y-\the\squigglecount\noexpand\endcsname {\the\pdflastypos} }}

\squiggleosc=\baselineskip \squigglesep=4pt \def\squigelamp{2}

Here is the definitive guide to the use of TeX, written by the system's creator, Donald E. Knuth. TeX represents the state of the art in computer typesetting. It is particularly valuable where the document, article, or book to be produced contains a lot of mathematics, and where the user \special{color push rgb 0 0 1}is\special{ color pop } \beginsquiggle concerned about typographic quality. TeX software offers both writers and publishers the opportunity to produce technical text of all kinds, in an attractive form, with the speed and efficiency of a computer system. Novice and expert users alike will gain from The TeXbook the level of information they seek. Knuth warns newcomers away from the more difficult areas, while he entices experienced users with new challenges. The novice need not learn much about \special{color push rgb 0 0 1}TeX\special{ color pop } \endsquiggle to prepare a simple manuscript with it. But for the preparation of more complex documents, The TeXbook contains all the detail required. Knuth's familiar wit, and illustrations specially drawn by Duane Bibby, add a light touch to an unusually readable software manual. The TeXbook is the first in a five-volume series on Computers and Typesetting, all authored by Knuth.

\bye

enter image description here

You will need two compilations to get the correct result.

There are three variables you can configure:

  • \squiggleosc is a dimen which controls length of the wave. The above example is with \squiggleosc=\baselineskip

  • \squigglesep is a dimen which controls the horizontal space between the squiggle and the text.

  • \squigelamp is a number that controls the amplitude of the wave.

Here is the result with

\squiggleosc=.5\baselineskip
\squigglesep=8pt
\def\squigelamp{4}

enter image description here

Udi Fogiel
  • 3,824
  • This looks like black magic for me at the moment, I will study the code carefully, thanks a lot –  Sep 01 '23 at 08:53
1

Note that it takes two runs for tikz to get the locations right.

\documentclass{book}
%\usepackage[marginparsep=1.5em]{geometry}
\usepackage{xcolor}
\usepackage{tikzpagenodes}
\usetikzlibrary{tikzmark}
\usepackage{ifoddpage}
\usepackage{lipsum}% random text

\newcounter{squiggle}% for unique tikzmark id \newcommand{\squiggles}{}% reserve global name

\newenvironment{squiggle}[1][5]% #1 = number of arcs (optional) {\xdef\squiggles{#1}% save argument \stepcounter{squiggle}% \tikzmark{squiggle.\thesquiggle}% \checkoddpage}% {\begin{tikzpicture}[overlay, remember picture] \path (pic cs:squiggle.\thesquiggle) ++(0,\ht\strutbox) coordinate(start); \coordinate (end) at (0,-\dp\strutbox); \ifoddpageoroneside \path (current page text area.east) ++(1pt,0) coordinate (left); \path (current page marginpar area.west) ++(-1pt,0) coordinate (right); \else \path (current page text area.west) ++(-1pt,0) coordinate (right); \path (current page marginpar area.east) ++(1pt,0) coordinate (left); \fi %\draw[red] (start-|left) rectangle (end-|right);% debug \path (start-|left); \pgfgetlastxy{\xleft}{\ytop}% \path (end-|right); \pgfgetlastxy{\xright}{\ybottom}% \pgfmathsetlengthmacro{\segment}{(\ytop-\ybottom)/\squiggles} \pgfmathsetmacro{\angle}{atan((\xright-\xleft)/\segment)}% \pgfmathsetlengthmacro{\R}{0.5\segment/sin(\angle)}% %\node[right] at (current page footer area.west) {\angle};% debug \coordinate (A) at (0.5\xleft+0.5*\xright, \ytop); \foreach \i in {1,2,...,\squiggles} {% \ifodd\i\relax \draw (A) arc[start angle=\angle, end angle=-\angle, radius=\R] coordinate(A); \else \draw (A) arc[start angle={180-\angle}, end angle={180+\angle}, radius=\R] coordinate(A); \fi } \end{tikzpicture}}

\begin{document} \lipsum[1] \begin{squiggle} \textcolor{red}{Squiggle should start on this line.} \lipsum[2] \textcolor{red}{Squiggle should end on this line.} \end{squiggle} \lipsum[3] \end{document}

demo

John Kormylo
  • 79,712
  • 3
  • 50
  • 120
  • This is an interesting solution for LaTeX, I will see if I manage to port it to TeX –  Aug 31 '23 at 16:21
  • You cannot really see the margin on this image. – Gaussler Sep 01 '23 at 08:31
  • It was cropped. The squiggle fits between the text area and the marginpar area. The (commented out) geometry line shows how to increase the width. BTW, have you tried the plain package? It will allow you to run TeX inside LaTeX. – John Kormylo Sep 01 '23 at 13:24