TransWikia.com

Can Gaussian (or similar) blur be applied to Tikz text?

TeX - LaTeX Asked by J. C. Salomon on February 21, 2021

I’m trying to emulate in TikZ a title page which I’ve previously drawn in SVG. The image below is from the SVG version, where the shadowed text is achieved using a feGaussianBlur filter. But everything I’ve found regarding filters and shadows and such with TikZ seems not to apply to text.

Is there a way to achieve this result?

Current code (translated by hand from the SVG and adapted to my book layout):

documentclass[11pt,extrafontsizes]{memoir}

setstocksize{9in}{6in}
settrimmedsize{stockheight}{stockwidth}{*}
medievalpage[12]
checkandfixthelayout

%usepackage{fontspec}
%newfontfamilygingerfont{RM Ginger}
%newcommand*{ginger}[1]{gingerfontfontsize{#1}{#1}selectfont}
newcommand*{ginger}[1]{normalfontfontsize{#1}{#1}selectfont}

usepackage{tikz}
usepackage{tikzpagenodes}
usetikzlibrary{calc,positioning,decorations.text}
tikzset{x=1in,y=1in}

begin{document}
thispagestyle{empty}
begin{tikzpicture}[remember picture,overlay,shift={($ (current page.south west) + (0.5, 0.5) $)}]

  node at (2.5, 7) [font=ginger{31.5}, anchor=base] {Unshadowed Text};

  draw[shift={(0, 5.75)}, decorate,
      decoration={text along path, text align=center,
      text={|ginger{40.5}|The Long Title}}]
    (0, 0) .. controls (1, 0.5) and (1.625, 0.625) .. (2.5, 0.625)
      .. controls (3.375, 0.625) and (4, 0.5) .. (5, 0);

  node at (2.5, 6.125) [font=ginger{31.5}, anchor=base] {of};

  draw[shift={(0, 5)}, decorate,
      decoration={text along path, text align=center,
      text={|ginger{81}|the Book}}]
    (0, 0) .. controls (1, 0.5) and (1.625, 0.625) .. (2.5, 0.625)
      .. controls (3.375, 0.625) and (4, 0.5) .. (5, 0);

  node at (2.5, 4.25) [font=ginger{47.25}, anchor=base] {A. U. Thor};

  node at (2.5, 3) [font=ginger{31.5}, anchor=base] {More unshadowed text};

  node at (2.5, 2.5) [font=ginger{27}, anchor=base] {and some more};
end{tikzpicture}
end{document}

What the SVG version looks like: Example title page with SVG blur

2 Answers

I guess my answer comes a little bit late, but I give it anyway. Who knows?

Some blurred text

I tried to produce the blurring effect using a double loop; thinking about one letter, the loops are moving it around circularly and outwardly.

The function forBlurring tries to adapt the size of the blurring effect to the size of the letter. The normal vs bold font should be considered also...

I tried to stick to your code. Since you use the text along path decoration, to be able to handle opacity, one must pass to text effects along path correspondingly. I did this in the blurring part of the code (the first part).

If you keep the parameters below, the compilation asks for some patience.

documentclass[11pt, extrafontsizes]{memoir}

newcommand*{ginger}[1]{normalfontfontsize{#1}{#1}selectfont}
newcommand*{bfginger}[1]{bfseriesfontsize{#1}{#1}selectfont}

usepackage{xcolor}
colorlet{blurColor}{black!75}

usepackage{tikz}
usetikzlibrary{math, calc, positioning, decorations.text}
tikzset{x=1in, y=1in}

begin{document}
thispagestyle{empty}

tikzmath{%
  integer N;
  N = 17; % 23;
  real op, tmp;
  op = .025;
  function forBlurring(i, s) {
    return i*s/61;
  };
}
begin{tikzpicture}[]
  foreach i in {.1, .3, .45, .6, .8}{%
    foreach j in {0, ..., N}{%
      tikzmath{ tmp = forBlurring(i, 41); }
      path[shift={($(0, 5.25)+({j/(N+1)*360} : tmp ex)$)}, decorate,
      decoration={%
        text effects along path, text align=center,
        text={The Long Title},
        text effects/.cd,
        characters={text along path, blurColor,
          opacity=op, font=bfginger{41}}
      }]
      (0, 0) .. controls (1, 0.5) and (1.625, 0.625) .. (2.5, 0.625)
      .. controls (3.375, 0.625) and (4, 0.5) .. (5, 0);

      node[font=bfginger{41}, anchor=base, blurColor, opacity=op]
      at ($(2.5, 5.15)+({j/(N+1)*360} : tmp ex)$) {of};

      tikzmath{ tmp = forBlurring(i, 61); }
      path[shift={($(0, 3.5)+({j/(N+1)*360} : tmp ex)$)}, decorate, 
      decoration={%
        text effects along path, text align=center,
        text={the Book},
        text effects/.cd,
        characters={text along path, blurColor,
          opacity=op, font=bfginger{61}}
      }]
      (0, 0) .. controls (1, 0.5) and (1.625, 0.625) .. (2.5, 0.625)
      .. controls (3.375, 0.625) and (4, 0.5) .. (5, 0);

      tikzmath{ tmp = forBlurring(i, 47); }
      node[font=ginger{47}, anchor=base, blurColor, opacity=op]
      at ($(2.5, 2.5)+({j/(N+1)*360} : tmp ex)$) {A. U. Thor};     
    }
  }
  
  node at (2.5, 7) [font=ginger{31}, anchor=base] {Unshadowed Text};

  draw[shift={(0, 5.25)}, decorate,
  decoration={%
    text along path, text align=center,
    text={|bfginger{41}|The Long Title}
  }]
  (0, 0) .. controls (1, 0.5) and (1.625, 0.625) .. (2.5, 0.625)
  .. controls (3.375, 0.625) and (4, 0.5) .. (5, 0);

  node at (2.5, 5.15) [font=bfginger{41}, anchor=base] {of};
  
  draw[shift={(0, 3.5)}, decorate, 
  decoration={%
    text along path, text align=center,
    text={|bfginger{61}|the Book}
  }]
  (0, 0) .. controls (1, 0.5) and (1.625, 0.625) .. (2.5, 0.625)
  .. controls (3.375, 0.625) and (4, 0.5) .. (5, 0);

  node at (2.5, 2.5) [font=ginger{47.25}, anchor=base] {A. U. Thor};

  node at (2.5, 1.25) [font=ginger{28}, anchor=base]
  {More unshadowed text};

  node at (2.5, .75) [font=ginger{28}, anchor=base]
  {and some more};
end{tikzpicture}

Correct answer by Daniel N on February 21, 2021

Less hackish, perhaps:

Setting the Text Render mode (PDF operator Tr) to 2 which is "fill & stroke" (normal is 0 = fill-only), then gradually reducing the line width and the stroke colour (from white to black) while overlaying the text on itself many times. Note that the text is not moved around to create the blur.

The intensity of the blur effect depends on the initial line width used for stroking the glyph outlines: the larger the more intense. The example could be extended to use different values for different font sizes.

And yes, one shouldn't forget to set the graphics state parameter "line join" to 1, meaning "round" to avoid sharp corners. enter image description here

documentclass[11pt,extrafontsizes,oneside]{memoir}

newcommand*{ginger}[1]{normalfontfontsize{#1}{#1}selectfont}
newcommand*{bfginger}[1]{bfseriesfontsize{#1}{#1}selectfont}

usepackage{tikz}
usetikzlibrary{calc,decorations.text}
tikzset{x=1in,y=1in}

begin{document}thispagestyle{empty}
begin{center}
begin{tikzpicture}
  node at (2.5, 7) [font=ginger{32}, anchor=base] {Unshadowed Text};
  
  foreach i in {0,1,...,100} {
    pgfmathsetmacro{lw}{8.0-i*0.08} % line width
    pgfmathsetmacro{lc}{1.0-i*0.01} % stroke colour
    pdfliteral{q          % save graphics state
      1 j                  % line join "Round"
      lwspace w          % line width
      2 Tr}                % text render mode: fill & stroke
      path[shift={(0, 5.25)}, decorate,
          decoration={text along path, text align=center,
          text={|bfginger{40}pdfliteral{lcspace G}|The Long Title}}]
        (0, 0) .. controls (1, 0.5) and (1.625, 0.625) .. (2.5, 0.625)
          .. controls (3.375, 0.625) and (4, 0.5) .. (5, 0);
    
      node at (2.5, 5.18) [font=bfginger{32}, anchor=base] {pdfliteral{lcspace G}of};
    
      path[shift={(0, 3.5)}, decorate,
          decoration={text along path, text align=center,
          text={|bfginger{60}pdfliteral{lcspace G}|the Book}}]
        (0, 0) .. controls (1, 0.5) and (1.625, 0.625) .. (2.5, 0.625)
          .. controls (3.375, 0.625) and (4, 0.5) .. (5, 0);
    pdfliteral{Q}         % restore graphics state
  }  
  
  node at (2.5, 2.5) [font=ginger{46}, anchor=base] {A. U. Thor};
  
  node at (2.5, 1.25) [font=ginger{32}, anchor=base] {More unshadowed text};
  
  node at (2.5, 0.75) [font=ginger{32}, anchor=base] {and some more};
end{tikzpicture}
end{center}
end{document}

This is a slightly improved example. Instead of directly typesetting the title page, we create an Opacity Mask (Fading, in TikZ parlance) in almost the same way as above. (The only difference: we vary the colour in the reverse direction from black to white, as black mask areas are fully transparent, white areas fully opaque.) This opacity mask allows us to combine arbitrary background and foreground colours.

enter image description here

documentclass[11pt,extrafontsizes,oneside]{memoir}

newcommand*{ginger}[1]{normalfontfontsize{#1}{#1}selectfont}
newcommand*{bfginger}[1]{bfseriesfontsize{#1}{#1}selectfont}

usepackage{tikz}
usetikzlibrary{calc,decorations.text}
tikzset{x=1in,y=1in}

pagestyle{empty}

begin{document}
pgfdeclarefading{titlemask}{%
  begin{tikzpicture}[text=white,/pgf/decoration/text color=white] % default text colour --> fully opaque
    node at (2.5, 7) [font=ginger{32}, anchor=base] {Unshadowed Text};
    foreach i in {0,1,...,100} {
      pgfmathsetmacro{lw}{8.0-i*0.08} % line width
      pgfmathsetmacro{lc}{i*0.01} % stroke colour
      pdfliteral{q          % save graphics state
        1 j                  % line join "Round"
        lwspace w          % line width
        2 Tr}                % text render mode: fill & stroke
        path[shift={(0, 5.25)}, decorate,
            decoration={text along path, text align=center,
            text={|bfginger{40}pdfliteral{lcspace G}|The Long Title}}]
          (0, 0) .. controls (1, 0.5) and (1.625, 0.625) .. (2.5, 0.625)
            .. controls (3.375, 0.625) and (4, 0.5) .. (5, 0);
        node at (2.5, 5.18) [font=bfginger{32}, anchor=base] {pdfliteral{lcspace G}of};
        path[shift={(0, 3.5)}, decorate,
            decoration={text along path, text align=center,
            text={|bfginger{60}pdfliteral{lcspace G}|the Book}}]
          (0, 0) .. controls (1, 0.5) and (1.625, 0.625) .. (2.5, 0.625)
            .. controls (3.375, 0.625) and (4, 0.5) .. (5, 0);
      pdfliteral{Q}         % restore graphics state
    }  
    node at (2.5, 2.5) [font=ginger{46}, anchor=base] {A. U. Thor};
    node at (2.5, 1.25) [font=ginger{32}, anchor=base] {More unshadowed text};
    node at (2.5, 0.75) [font=ginger{32}, anchor=base] {and some more};
    % save corners and centre of the mask
    pgfpointanchor{current bounding box}{south west}
    pgfgetlastxy{maskllx}{masklly}xdefmaskll{maskllx,masklly}
    pgfpointanchor{current bounding box}{north east}
    pgfgetlastxy{maskurx}{maskury}xdefmaskur{maskurx,maskury}
    pgfpointanchor{current bounding box}{center}
    pgfgetlastxy{maskcx}{maskcy}xdefmaskc{maskcx,maskcy}
  end{tikzpicture}%
}

begin{center}
begin{tikzpicture}
fill[scope fading=titlemask, fit fading=false,  % install mask on black rectangle
        fading transform={shift={(maskc)}}] (maskll) rectangle (maskur);
end{tikzpicture}
end{center}

newpagepagecolor{yellow!10}

begin{center}
begin{tikzpicture}
fill[scope fading=titlemask, fit fading=false, fill=red!80!black, % ditto, but red rectangle
        fading transform={shift={(maskc)}}] (maskll) rectangle (maskur);
end{tikzpicture}
end{center}
end{document}

Answered by AlexG on February 21, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP