7

I would like to add a random white space at the begining of each line in a flushleft typeset paragraph. The idea is to simulate a hand-written manuscript.

I thought I could do trick lineno package to do this but that's not the logic. Any idea would be welcome.


Follow-up question

Sašo Živanović's solution works, but in a similar context, it conflicts with a previously defined macro: the paragraph shape remains normal.

% Based on some ideas from http://tex.stackexchange.com/a/29458
\documentclass{article}

% thanks to Bruno Le Floch
\usepackage{rotating}
\usepackage[first=-3,last=5]{lcg}% you can play around with these values
\makeatletter
\newcommand{\globalrand}{\rand\global\cr@nd\cr@nd}
\makeatother
\newcommand{\randomrotation}[1]{\globalrand\turnbox{\value{rand}}{#1}\phantom{#1‌​}}
% thanks...
\makeatletter
\def\handmove#1{%
  \@handmove#1 \@empty }
\def\@handmove#1 #2{%
  \randomrotation{#1}\space
  \ifx #2\@empty
  \else
    \expandafter\@handmove
  \fi
  #2%
}
\makeatother

%la macro de Saso Zivanovic
\usepackage{pgf,pgffor}
\usepackage{etoolbox}

\def\randomflushleftpercent{0.3}
\def\randomflushleftn{42}

\newenvironment{randomflushleft}{%
  \raggedright
  \everypar={\computerandomparshape}
}{}

\def\computerandomparshape{%
  \gdef\myparshape{\parshape\randomflushleftn\space}%
  \foreach \n in {1,2,...,\randomflushleftn} {%
    \pgfmathparse{rnd*\randomflushleftpercent*\textwidth}%
    \xappto\myparshape{\pgfmathresult pt }%
    \pgfmathparse{\textwidth-\pgfmathresult}%
    \xappto\myparshape{\pgfmathresult pt }%
  }%
  \myparshape
}
\begin{document}
\pagestyle{empty}
\begin{randomflushleft}
  \handmove{Solacia dua, nequaquam paria tanto dolori, solacia
    tamen. Solacia dua, nequaquam paria tanto dolori, solacia
    tamen. Solacia dua, nequaquam paria tanto dolori, solacia
    tamen.}
\end{randomflushleft}
\end{document}

Wrong result

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
tradog
  • 71

2 Answers2

8

enter image description here

\documentclass{article}

\textwidth.3\textwidth

\begin{document}


\def\a{One two three four five six seven eight nine ten. }
\def\b{\a\a\a  Red green blue yellow white black. \a}

\def\p#1{#1 \dimexpr\textwidth-#1\relax}
\raggedright
\itshape
\parshape 20 
\p{1pt}\p{3pt}\p{1pt}\p{2pt}\p{3pt}
\p{2pt}\p{1pt}\p{4pt}\p{1pt}\p{3pt}
\p{1pt}\p{3pt}\p{5pt}\p{2pt}\p{1pt}
\p{3pt}\p{2pt}\p{3pt}\p{1pt}\p{2pt}
\b

\end{document}

Here I just made up the "random" list of offsets but you could if necessary generate that using a random number generator (from pgfmath or whatever you choose)

David Carlisle
  • 757,742
8

As David suggested ... randomly generated \parshape.

42 should be something large enough. \randomflushleftpercent determines the maximum amount (in percent of text width) of the whitespace on the left.

\documentclass{article}
\usepackage{lipsum}

\usepackage{pgf,pgffor}
\usepackage{etoolbox}

\def\randomflushleftpercent{0.1}
\def\randomflushleftn{42}

\newenvironment{randomflushleft}{%
  \raggedright
  \everypar={\computerandomparshape}
}{}

\def\computerandomparshape{%
  \gdef\myparshape{\parshape\randomflushleftn\space}%
  \foreach \n in {1,2,...,\randomflushleftn} {%
    \pgfmathparse{rnd*\randomflushleftpercent*\textwidth}%
    \xappto\myparshape{\pgfmathresult pt }%
    \pgfmathparse{\textwidth-\pgfmathresult}%
    \xappto\myparshape{\pgfmathresult pt }%
  }%
  \myparshape
}

\begin{document}
\parskip 1ex

\begin{randomflushleft}
  \lipsum
\end{randomflushleft}

\end{document}

Answer to the follow-up

There was an (unfortunate) interaction between \parshape-setting within \everypar and a group introduced by \handmove. \everypar tokens are inserted just before the horizontal mode is entered for the paragraph. When the \handmove{...} was the first thing in a paragraph, \everypar was thus called within a group opened by \turnbox. This group was closed before the end of the paragraph, causing the set \parshape to be forgotten. Solution: start \handmove with an \mbox{}.

There was a similar situation at the end of the randomflushleft environment. The paragraph hasn't ended yet, but the group introduced by randomflushleft got closed. Solution: end randomflushleft with an explicit \par.

\documentclass[draft]{article}
\usepackage[utf8x]{inputenc}
\usepackage{lipsum}

% thanks to Bruno Le Floch
\usepackage{rotating}
\usepackage[first=-3,last=5]{lcg}% you can play around with these values
\makeatletter
\newcommand{\globalrand}{\rand\global\cr@nd\cr@nd}
\makeatother
\newcommand{\randomrotation}[1]{\globalrand\turnbox{\value{rand}}{#1}\phantom{#1‌​}}
% thanks...
\makeatletter
\def\handmove#1{%
  \mbox{}\@handmove#1 \@empty }
\def\@handmove#1 #2{%
  \randomrotation{#1}\space
  \ifx #2\@empty
  \else
    \expandafter\@handmove
  \fi
  #2%
}
\makeatother

%la macro de Saso Zivanovic
\usepackage{pgf,pgffor}
\usepackage{etoolbox}

\def\randomflushleftpercent{0.3}
\def\randomflushleftn{42}

\makeatletter
\newenvironment{randomflushleft}{%
  \everypar={\randomparshape}%
  \raggedright
  \rightskip \z@ plus2em
}{\par}
\makeatother

\def\randomparshape{%
  \xdef\myparshape{\noexpand\parshape\randomflushleftn\space}%
  \foreach \n in {1,2,...,\randomflushleftn} {%
    \pgfmathparse{rnd*\randomflushleftpercent*\textwidth}%
    \xappto\myparshape{\pgfmathresult pt
      \the\dimexpr\textwidth-\pgfmathresult pt\relax\space}%
  }%
  \myparshape
}
\begin{document}
\pagestyle{empty}
\parskip 2ex

\begin{randomflushleft}
  \handmove{Solacia dua, nequaquam paria tanto dolori, solacia
    tamen. Solacia dua, nequaquam paria tanto dolori, solacia
    tamen. Solacia dua, nequaquam paria tanto dolori, solacia
    tamen.}
\end{randomflushleft}

\end{document}

The correct result

There are also some further changes in the code, most just beautifiers, but one quite important: without \rightskip \z@ plus2em in the definition of randomflushleft, the first line can end too soon. I find this a very interesting phenomen: I have posted a question about it.