Outline text using TrueType fonts

Here is a pdflatex (as well as XeLaTeX) approach. I create a macro \shadowfy that can span paragraphs, but can't handle macros in its arguments. The approach may not be efficient, but it is simple. It parses the argument, eventually letter by letter, and then stacks a bunch (N, S, E, W, NE, SE, SW, NW) of +/-kerned and raised/lowered \secondarycolor copies of the letter, finally laying an unkerned, unraised \primarycolor copy of the letter atop it. With the use of \def\useanchorwidth{T} in the \shadow definition, it will preserve the letter width of the original letters. If you comment that line out, the letter spacing will increase to account for the horizontal offset.

The user may set these parameters:

\setlength\shadowHoffset{.16pt}
\setlength\shadowVoffset{.08pt}
\def\primarycolor{white}
\def\secondarycolor{black}

Here is the MWE. Because of a "quirk" that I could fix with added code, the value of \shadowHoffset should be set to double the value of \shadowVoffset if a uniform horizontal/vertical shadow effect is desired. As you can see, the thickness of the shadow line can be controlled, as well as the colors.

\documentclass{article}
\usepackage{stackengine,xcolor}

\newcommand\shadowfy[1]{\expandafter\shadowfypars#1\par\relax\relax}
\long\def\shadowfypars#1\par#2\relax{%
  \ifx#1\relax\else
    \shadowfywords#1 \relax\relax%
  \fi%
  \ifx\relax#2\else\par\shadowfypars#2\relax\fi%
}
\def\shadowfywords#1 #2\relax{%
  \ifx#1\relax\else
    \shadowfyletters#1\relax\relax%
  \fi%
  \ifx\relax#2\else\ \shadowfywords#2\relax\fi%
}
\def\shadowfyletters#1#2\relax{%
  \shadow{#1}%
  \ifx\relax#2\else\shadowfyletters#2\relax\fi}

\newlength\shadowHoffset
\newlength\shadowVoffset
\setlength\shadowHoffset{.2pt}
\setlength\shadowVoffset{.1pt}
\def\primarycolor{white}
\def\secondarycolor{black}

\def\shadow#1{\setstackgap{L}{0pt}\def\stacktype{L}%
\def\useanchorwidth{T}% CAN BE COMMENTEDD FOR MORE INTERLETTER SPACE.
\Longstack{%
\raisebox{0pt}{\textcolor{\primarycolor}{#1}} 
\kern.7\shadowHoffset\raisebox{.7\shadowVoffset}{\textcolor{\secondarycolor}{#1}}
\kern-.7\shadowHoffset\raisebox{.7\shadowVoffset}{\textcolor{\secondarycolor}{#1}}
\kern\shadowHoffset\raisebox{0pt}{\textcolor{\secondarycolor}{#1}}
\kern-\shadowHoffset\raisebox{0pt}{\textcolor{\secondarycolor}{#1}}
\kern.7\shadowHoffset\raisebox{-.7\shadowVoffset}{\textcolor{\secondarycolor}{#1}}
\kern-.7\shadowHoffset\raisebox{-.7\shadowVoffset}{\textcolor{\secondarycolor}{#1}}
\kern0pt\raisebox{\shadowVoffset}{\textcolor{\secondarycolor}{#1}}
\kern0pt\raisebox{-\shadowVoffset}{\textcolor{\secondarycolor}{#1}}%
}}
\begin{document}
\newcommand\mytext{%
This is some sample shadow text.

Multiple paragraphs.
}%
\shadowfy{\mytext}

\setlength\shadowHoffset{.4pt}
\setlength\shadowVoffset{.2pt}
\def\primarycolor{yellow!70}
\def\secondarycolor{blue!80!black}
\shadowfy{\mytext}


\end{document}

enter image description here

enter image description here


I know the OP wants Xelatex solutions, and here I give a pdf solution, so i don't expect any votes, but wanted to show it anyhow, because it is so less grainy than the other answer of mine.

For this different answer, I steal from our most excellent LaTeX colleague Malipivo, extracting bits of \pdfliteral code from his answer at TikZ: halo around text? that end up in my macro \outline. I then basically substitute this \outline macro for the \shadow macro in my prior answer. The surrounding \shadowfy construct allows line breaking to work (albeit without hyphenation).

EDITED to incorporate Herbert's answer to this question (the \usecolor macro), Convert color name to pdfliteral code, so that colors can be specified in the LaTeX way, rather than as RGB triplets. This also has the advantage than CMYK colors are now not a problem.

Border and fill colors are defined with \bordercolor{} and \fillcolor{}, respectively. Thickness of border defined with \def\thickness{<decimal>}, though I don't know the units of the decimal.

\documentclass{article}
\usepackage{xcolor}
\input pdf-trans
\newbox\qbox
\def\usecolor#1{\csname\string\color@#1\endcsname\space}
\newcommand\bordercolor[1]{\colsplit{1}{#1}}
\newcommand\fillcolor[1]{\colsplit{0}{#1}}
\newcommand\outline[1]{\leavevmode%
  \def\maltext{#1}%
  \setbox\qbox=\hbox{\maltext}%
  \boxgs{Q q 2 Tr \thickness\space w \fillcol\space \bordercol\space}{}%
  \copy\qbox%
}
\newcommand\shadowfy[1]{\expandafter\shadowfypars#1\par\relax\relax}
\long\def\shadowfypars#1\par#2\relax{%
  \ifx#1\relax\else
    \shadowfywords#1 \relax\relax%
  \fi%
  \ifx\relax#2\else\par\shadowfypars#2\relax\fi%
}
\def\shadowfywords#1 #2\relax{%
  \outline{#1}%
  \ifx\relax#2\else\ \shadowfywords#2\relax\fi%
}
\newcommand\colsplit[2]{\colorlet{tmpcolor}{#2}\edef\tmp{\usecolor{tmpcolor}}%
  \def\tmpB{}\expandafter\colsplithelp\tmp\relax%
  \ifnum0=#1\relax\edef\fillcol{\tmpB}\else\edef\bordercol{\tmpC}\fi}
\def\colsplithelp#1#2 #3\relax{%
  \edef\tmpB{\tmpB#1#2 }%
  \ifnum `#1>`9\relax\def\tmpC{#3}\else\colsplithelp#3\relax\fi
}
\begin{document}
\bordercolor{black}
\fillcolor{white}
\def\thickness{.1}
\newcommand\mytext{This is some sample shadow text.\par Multiple paragraphs.}%
\shadowfy{\mytext}

\def\thickness{0.15}
\bordercolor{blue!70!black}
\fillcolor{yellow}
\shadowfy{\mytext}

\bordercolor{black}
\fillcolor{white}
\def\thickness{.02}{\Huge\shadowfy{a}}
\end{document}

enter image description here enter image description here

Here is a \Huge letter "a", with the settings

\bordercolor{black}
\fillcolor{white}
\def\thickness{.02}

enter image description here