[Tex/LaTex] Outline text characters

text-decorationstikz-pgf

In order to improve readability of some texts, I'd like to put a kind of "eyeliner" around my letters (actually, that's how memes manage to get readable texts on any picture).

Here is an exemple of what I have:

enter image description here

And what I want:

enter image description here

You can use if needed some lua code, as I'll use it with lualatex (and custom fonts).

Thank you!

MWE:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\tikz\node[fill=red,circle]{\color{white}\textbf{Hello} world};
\end{document}

–EDIT–

As stated in the comments, the contour package works great, except with custom fonts. Any idea for this font (compile with lualatex and put the font .ttf file in the font/ folder):

\documentclass{article}
% Special font
\usepackage{fontspec}
\setmainfont[Path=fonts/]{Heartbeat_in_Christmas.ttf}

\usepackage{tikz}
\usepackage[outline]{contour}
\begin{document}
\tikz\node[fill=red,circle]{\contour{black}{\protect\color{white}\textbf{Hello} world}};
\end{document}

— EDIT 2 —

I found the solution when I use lualatex: I just need to use \usepackage{contour} instead of \usepackage[outline]{contour}!

— EDIT 3 —
The solution of using with pdfrender + tikz to superpose texts works also great, except for a few chars with sharp angles:

enter image description here

Here is the text:

    \begin{tikzpicture} \node at (0,0) {%
        \textpdfrender{
          TextRenderingMode=FillStrokeClip,
          LineWidth=.8mm,
          FillColor=white,
          StrokeColor=black,
        }{mmmnnn}%
      };
      \node at (0,0) {mmmnnn};
    \end{tikzpicture}

— EDIT 5 —
Adding MiterLimit=1 avoid these strange shark edges, now it's better, there is just a minor hole in the letters m and n, in my font, but it's not important:

enter image description here

Thank you!

Best Answer

With the help of people in the comments, I finally came out with several solutions depending on what I need:

If you don't use lualatex and your font is supported (efficient solution)

Just use \usepackage[outline]{contour} and then \contour{green}{yourtext}

If you use lualatex, you can do (inneficient version):

Just use \usepackage{contour} and then \contour{green}{yourtext}. However, it is not really efficient because it will create lot's of copies. enter image description here

If you use lualatex and you want a thin border (efficient solution)

Then use the package \usepackage{pdfrender}, and use it this way:

\textpdfrender{
          TextRenderingMode=FillStrokeClip,
          LineWidth=.1pt,
          FillColor=white,
          StrokeColor=black,
          MiterLimit=1
        }{Your text}

However, if the stroke line is too big, then it will hide the text. Also, I don't know why, but if you do that, tikz picture does not longer work... Why???

enter image description here

If you use lualatex and you want a thick border and your text is short ("efficient" solution)

Then, the only solution I found is to draw twice the text, and use a tikzpicture to put them on top of the other one. The problem of this solution is that

\begin{tikzpicture}[anchor=base, baseline] \node at (0,0) {%
    \textpdfrender{
      TextRenderingMode=FillStrokeClip,
      LineWidth=1pt,
      FillColor=white,
      StrokeColor=black,
      MiterLimit=1
    }{Your text}%
  };
  \node at (0,0) {Your text};
\end{tikzpicture}

However, here it does not break the line in a paragraph, if you have a solution for that, please let me know. The inneficient solution 2 solve this problem.

enter image description here

All the solutions in one file:

\documentclass{article}
% Fonts
% \usepackage{fontspec}
% \setmainfont[Path=fonts/]{Heartbeat_in_Christmas.ttf}

\usepackage{tikz}
\usetikzlibrary{positioning}
% \usepackage[outline]{contour} % Sol 1
\usepackage{pdfrender} % Sol 2 & 3
\usepackage{contour} % Sol 4
\begin{document}
% \contour{green}{\color{blue}\textbf{Hello} world, I like it.}

Solution 1: Does not work with lualatex, only pdftex.

Solution 2: Not really efficient
\contour{green}{\color{blue}Your text}

Solution 3: (thin stroke)%
\textpdfrender{
  TextRenderingMode=FillStrokeClip,
  LineWidth=.1pt,
  FillColor=blue,
  StrokeColor=green,
  MiterLimit=1
}{Your text}%
\textpdfrender{
  TextRenderingMode=FillStrokeClip,
  LineWidth=.5pt,
  FillColor=blue,
  StrokeColor=green,
  MiterLimit=1
}{Your text}

Solution 4: On single line texts (comment solution 3 to see it, no idea why...)%
\begin{tikzpicture}[anchor=base, baseline]
\node at (0,0) {\textpdfrender{
          TextRenderingMode=FillStrokeClip,
          LineWidth=1pt,
          FillColor=blue,
          StrokeColor=green,
          MiterLimit=1
        }{Your text}};
\node at (0,0) {\color{blue}Your text};
\end{tikzpicture}

\end{document}