Chalkboard texture for tikz lines

It takes ages.

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{decorations,backgrounds}
\pgfkeys{decoration/.cd,
  iterations/.store in=\pgfdecorationiterations, iterations=75,
  radius/.store in=\pgfdecorationradius, radius=0.25pt,
}
\pgfdeclaredecoration{chalk}{draw}{
\state{draw}[width=\pgfdecorationsegmentlength]{
\pgftransformxshift{0.5\pgfdecorationsegmentlength/2}
\pgfmathloop
\ifnum\pgfmathcounter>\pgfdecorationiterations
\else
\pgfpathcircle{\pgfpointpolar{rnd*360}{rnd*\pgfdecorationsegmentamplitude}}%
{\pgfdecorationradius}%
\repeatpgfmathloop
}}
\begin{document}
\begin{tikzpicture}[background rectangle/.style={fill=black},
  show background rectangle, chalk/.style={fill=white, decorate, 
  decoration={chalk, segment length=1.5pt, amplitude=3pt}
  },looseness=0.25]
\path [chalk] (1/8,2) -- (0,1/2) arc (180:315:1/2) (-1/2,3/2)
  to [bend right] (5/8,3/2);
\path [chalk, shift=(0:1)] (1/8,1) to [bend left] (0,0);
\path [chalk, shift=(0:3/2)] (1/8,2) to [bend left] (0,0)
   (2/3,1) -- (1/16,2/3) -- (2/3,0);
\path [chalk, shift=(0:5/2)] (0,1) to [bend left] (1,1)
   to [bend left] (0,0) to [bend left] (1,0);
\path [chalk] (-1,-3/4) to [bend left] (9/2,-1/2);
\end{tikzpicture}
\end{document}

enter image description here


The following code looks like @Mark Wibrow's answer but takes only 20 seconds to compile. The idea is that instead of drawing millions of points, we draw thousands of dotted lines with various width, phase, pattern, and shift, which corresponding to \a, \b, \c, and \d in my code.

\documentclass[border=9,tikz]{standalone}
\usetikzlibrary{backgrounds,decorations.pathreplacing}
\begin{document}

\def\iterate{400}
\def\rollabcd{
    \pgfmathsetmacro\a{(1+rnd)/4}
    \pgfmathsetmacro\b{5+5*rnd}
    \pgfmathsetmacro\c{\b*rnd}
    \pgfmathsetmacro\d{rnd*3}
}
\tikzset{
    draw abcd/.style={
        white,line cap=round,
        line width=\a,
        dash pattern=on 0 off \b,
        dash phase=\c,
        shift={(rnd*360:\d pt)}
    },
    chalk/.style={
        decorate,
        decoration={
            show path construction,
            lineto code={
                \foreach\i in{1,...,\iterate}{
                    \rollabcd
                    \draw[draw abcd](\tikzinputsegmentfirst)--(\tikzinputsegmentlast);
                }
            },
            curveto code={
                \foreach\i in{1,...,\iterate}{
                    \rollabcd
                    \draw[draw abcd](\tikzinputsegmentfirst)..controls(\tikzinputsegmentsupporta)
                                          and(\tikzinputsegmentsupportb)..(\tikzinputsegmentlast);
                }
            },
            closepath code={
                \foreach\i in{1,...,\iterate}{
                \rollabcd
                    \draw[draw abcd](\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
                }
            }
        }
    }
}

\tikz[background rectangle/.style={fill=black},show background rectangle,looseness=0.25]{
\path [chalk] (1/8,2) -- (0,1/2) arc (180:315:1/2) (-1/2,3/2)
  to [bend right] (5/8,3/2);
\path [chalk, shift=(0:1)] (1/8,1) to [bend left] (0,0);
\path [chalk, shift=(0:3/2)] (1/8,2) to [bend left] (0,0)
   (2/3,1) -- (1/16,2/3) -- (2/3,0);
\path [chalk, shift=(0:5/2)] (0,1) to [bend left] (1,1)
   to [bend left] (0,0) to [bend left] (1,0);
\path [chalk] (-1,-3/4) to [bend left] (9/2,-1/2);
}

\end{document}

Possible Optimization

The alphabet is taken from Custom line cap to simulate inked line in TikZ.
The current approach replace each Bezier curve by 32 dotted curves.
For each dotted curve, roll dice to determine

  • the dash pattern and dash phase
  • shift
  • line cap (either round or rect)
  • color (either black or white)

It takes 10 seconds to compile

\documentclass[border=9,tikz]{standalone}
\usetikzlibrary{backgrounds,decorations.pathreplacing}
\begin{document}

\def\niterate{32}
\def\rolldice{
    \pgfmathsetmacro\rndlinewidth{32/(8+\i)}
    \pgfmathsetmacro\rndoff{4+8*rnd}
    \pgfmathsetmacro\rndshift{((4-\rndlinewidth)*256*rnd)^.25}
    \pgfmathrandomitem\rndcap{cap}
    \pgfmathsetmacro\rnddark{rnd<.3?100:0}
}
\pgfmathdeclarerandomlist{cap}{{round}{rect}}
\tikzset{
    put dots/.style={
        /utils/exec=\rolldice,
        line width=\rndlinewidth,
        dash pattern=on 0 off \rndoff,
        dash phase=(1+\rndoff)*rnd,
        shift={(rnd*360:\rndshift pt)},
        line cap=\rndcap,
        black!\rnddark,
    },
    chalk/.style={
        decorate,
        decoration={
            show path construction,
            lineto code={
                \foreach\i in{1,...,\niterate}{
                    \draw[put dots]
                        (\tikzinputsegmentfirst)--(\tikzinputsegmentlast);
                }
            },
            curveto code={
                \foreach\i in{1,...,\niterate}{
                    \draw[put dots]
                        (\tikzinputsegmentfirst)..controls
                    (\tikzinputsegmentsupporta)and(\tikzinputsegmentsupportb)
                        ..(\tikzinputsegmentlast);
                }
            },
            closepath code={
                \foreach\i in{1,...,\niterate}{
                \draw[put dots]
                    (\tikzinputsegmentfirst)--(\tikzinputsegmentlast);
                }
            }
        }
    },
}
\tikzset{
    A/.pic={\draw[chalk] 
    (0,-0.55) -- (0.3,0.4) -- (0.6,-0.55);
    \draw[chalk](0.1,1/3-0.45) --
    (0.5,1/3-0.45);
    \path (0.7,0);},
    B/.pic={\draw[chalk] (0,-0.45) -- (0,0.45)
    to[out=0,in=0,looseness=2.5]    (0,0)   to[out=0,in=0,looseness=3] cycle;},
    C/.pic={\draw[chalk]
     (0,0) to[out=90,in=110,looseness=2]    (0.5,0.25);
     \draw[chalk](0,0) to[out=-90,in=-110,looseness=2]  (0.5,-0.25);
     \path (0.7,0);},
    D/.pic={\draw[chalk] (0,-0.45) -- (0,0.45) 
    to[out=0,in=0,looseness=2.25]    cycle;
    \path (0.7,0);},
    E/.pic={\draw[chalk] 
    (0.5,-0.45) --(0,-0.45) -- (0,0.45) -- (0.5,0.45);
    \draw[chalk] (0,0) -- (0.5,0);
    \path (0.7,0);},
    F/.pic={\draw[chalk] 
    (0,-0.45) -- (0,0.45)   -- (0.5,0.45);
    \draw[chalk] (0,0) -- (0.5,0);
    \path (0.7,0);},
    G/.pic={\draw[chalk]
     (0,0) to[out=90,in=110,looseness=2]    (0.5,0.25);
     \draw[chalk] (0,0) to[out=-90,in=-110,looseness=2] 
     (0.5,-0.25);
     \draw[chalk] (0.54,-0.25) to (0.3,-0.25);
     \path (0.7,0);},
    H/.pic={\draw[chalk] 
    (0,-0.5) -- (0,0.5);    
    \draw[chalk] (0.5,-0.5) -- (0.5,0.5);
    \draw[chalk] (0,0) -- (0.5,0);
    \path (0.7,0);},
    I/.pic={\draw[chalk] (0,-0.45) -- (0,0.45);
    \path (0.25,0);},
    J/.pic={\draw[chalk] (0.2,0.45) -- (0.2,-0.35) to[out=-90,in=0]
    (0.1,-0.45) to[out=180,in=-90] (0,-0.35);
    \path (0.45,0);},
    K/.pic={\draw[chalk] 
    (0,-0.45) -- (0,0.45); 
    \draw[chalk] (0.4,0.45) -- (0.02,0) --  (0.4,-0.45);
    \path (0.6,0);},
    L/.pic={\draw[chalk] 
    (0,0.5) -- (0,-0.45) -- (0.4,-0.45);
    \path (0.6,0);},
    M/.pic={\draw[chalk] (0,-0.45) -- (0,0.45) -- 
    (0.3,0.25) -- (0.6,0.45) -- (0.6,-0.45);
    \path (0.8,0);},
    N/.pic={\draw[chalk] (0,-0.45) -- (0,0.45) -- (0.6,-0.4) --
    (0.6,0.45);
    \path (0.8,0);},
    O/.pic={\draw[chalk] (0.3,0) circle(0.3 and 0.48);
    \path (0.8,0);},
    P/.pic={\draw[chalk] (0,-0.45) -- (0,0.45) 
    to[out=0,in=0,looseness=2.5]    (0,0);
    \path (0.6,0);},
    Q/.pic={\draw[chalk] 
    (0.3,0) circle(0.3 and 0.48);
    \draw[chalk](0.35,-0.25) -- (0.6,-0.45);
    \path (0.8,0);},
    R/.pic={\draw[chalk] 
    (0,-0.45) -- (0,0.45) 
    to[out=0,in=0,looseness=2.5]    (0.05,0) -- (0.4,-0.45);
    \path (0.6,0);},
    S/.pic={\draw[chalk] (0.5,0.4)  
    to[out=160,in=165,looseness=2]  (0.3,0) 
    to[out=-15,in=-20,looseness=2] (0.1,-0.4);
    \path (0.65,0);},
    T/.pic={\draw[chalk] (0.35,-0.45) -- (0.35,0.45) (0,0.45) -- (0.7,0.45);
    \path (0.85,0);},
    U/.pic={\draw[chalk] (0,0.5) -- (0,0) to[out=-90,in=-90,looseness=2.5]
    (0.6,0) -- (0.6,0.5);
    \path (0.8,0);},
    V/.pic={\draw[chalk] (0,0.5) -- (0.3,-0.4) -- (0.6,0.5);
    \path (0.8,0);},
    W/.pic={\draw[chalk] (0,0.45) -- (0.3,-0.4) -- (0.45,-0.1)
    -- (0.6,-0.4) -- (0.9,0.45);
    \path (1.1,0);},
    X/.pic={\draw[chalk] 
    (0,0.45) -- (0.6,-0.45);
     \draw[chalk] (0.6,0.45)
    -- (0,-0.45);
    \path (0.8,0);},
    Y/.pic={\draw[chalk] 
    (0,0.45) -- (0.3,0);    
    \draw[chalk] (0.6,0.45)
    -- (0,-0.45);
    \path (0.8,0);},
    Z/.pic={\draw[chalk] (0,0.45) --(0.6,0.45) -- (0,-0.45) 
    -- (0.6,-0.45);
    \path (0.8,0);},
    space/.pic={\path (0,0) (0.2,0);},
}
\tikz[every pic/.style={scale=4},scale=3]{
    \fill(0,-2)rectangle(9,8);
    \begin{scope}[overlay]
        \path foreach\X[count=\x]in {A,...,G}{(\x,6)pic{\X}};
        \path foreach\X[count=\x]in {H,...,N}{(\x,4)pic{\X}};
        \path foreach\X[count=\x]in {O,...,U}{(\x,2)pic{\X}};
        \path foreach\X[count=\x]in {V,...,Z}{(\x,0)pic{\X}};
    \end{scope}
}


\message{^^J^^J time = \the\numexpr\pdfelapsedtime*1000/65536 ms ^^J^^J}

\end{document}


This isn't quite what the OP asks, but it is along those lines. It uses the handwritten Teen Spirit Font (fts), superimposed with a random dot pattern, using JLDiaz's answer at How to have a real random pattern?, using the \specw[<speckle count per letter>]{word}

\documentclass{article}
\usepackage{tikz,stackengine}
\pagecolor{black}
\color{white}
\newcommand\speckle[2][50]{%
  \setbox0=\hbox{\color{white}#2}%
  \stackinset{c}{}{c}{}{%
  \color{black}%
    \begin{tikzpicture}
      \foreach \i in {1,...,#1}
      \fill (rnd*\wd0, rnd*\ht0) circle (.25pt);
    \end{tikzpicture}%
  }%
  {\copy0}%
}
\newcommand\specw[2][75]{%
  \specwaux{#1}#2\relax\relax\relax%
}
\def\specwaux#1#2#3\relax{%
  \ifx\relax#2\else\speckle[#1]{#2}\specwaux{#1}#3\relax\fi%
}
\begin{document}
\centering
\fontfamily{fts}\selectfont
\specw[30]{Today\,s} \specw[90]{Lesson:}

\specw[300]{{\scalebox{3}{\char116}}}
\specw[700]{{\scalebox{3}{\char64}}}
\specw[1000]{{\scalebox{3}{U}}}
\end{document}

enter image description here

At the expense of compilation time, one can decrease the size of the dots (from .25pt to .10pt) and double the number of dots:

enter image description here

For comparison, without speckles, it looks like this:

enter image description here