29

A couple months back, I recall reading an article where LaTeX's metatype system is used to have a document fade from one font into another. The example had several pages of serif text that slowly transitioned into a sans-serif font by the end of the document - the change was subtle enough to not be noticeable, but the end effect was rather dramatic (serif vs sans serif).

The question is, how can I do this in my own document? I tried searching on CTAN, but no result came up.

Would there be a package that would allow me to accomplish this?


EDIT:

The closest thing I could find fitting this description is

enter image description here

[From Douglas R. Hofstadter's 'Meta-Font, Metamathematics, and Metaphysics: Comments on Donald Knuth's "The Concept of a Meta-Font"'. Reprinted as figure 12.1 in Metamagical Themas, p. 241. The article is included as chapter 13 in the same collection, together with a postscript. The example is from Knuth's paper in Visible Language 16.1 (1982) and is available as PDF from the journal's online archive. But don't click the link if you have a slow connection!]

Can something like this be applied to a longer text?

  • 3
    I guess you don’t have a link for the article?! – Tobi Sep 20 '16 at 15:56
  • 3
    If you don't have the article's name or a link to it, could you please provide us with the name of which site or magazine it may have come from? That would really help us to find an answer to your question. – J.D. Sep 21 '16 at 3:06
  • 1
    peterpacz1, "Last seen Feb 22 at 12:04", we might never know what that document was, folks… – Clément Sep 21 '16 at 18:08
  • According to here, it was Scientific American, December 1982 – Oleg Soloviev Sep 22 '16 at 16:19
  • But it seems be not true – Oleg Soloviev Sep 22 '16 at 16:25
13
+50

APPROACH 1

This is a poor man's imitation, I think, of what is sought. It does not work by evolving the font construction; rather, it works through a fading mechanism between two fixed fonts. Thus, in the intermediate regime, there is visible overlay.

By setting \fadefrom and \fadeto, you can choose the starting and final destinations, as I have done thrice below. Currently, the letter width of the result is the wider of the two fonts, so changing to a font of very different width would not work well.

This uses a \FadeAfter{<length>}{<text>} syntax.

\documentclass{article}
\usepackage{xcolor,stackengine,tikz}
\newcommand\fadefrom{}
\newcommand\fadeto{\textsf}
\newcommand\fade[1]{%
  \edef\antitwo{\the\numexpr100-#2\relax}%
  \ifnum\antitwo>99\relax\def\antitwo{99}\else%
    \ifnum\antitwo<10\relax\edef\antitwo{0\antitwo}\else%
      \ifnum\antitwo<1\relax\def\antitwo{1}\fi\fi\fi%
  \ifnum#2>50\relax
    \stackengine{0pt}%
      {\tikz\node[inner sep=0pt, opacity=1]{%
      \textcolor{black!\antitwo}{\strut\fadeto{#1}}};}%
      {\tikz\node[inner sep=0pt, opacity=1]{\textcolor{black!#2}{\strut\fadefrom{#1}}};}%
      {O}{c}{F}{F}{L}%
  \else%
    \stackengine{0pt}%
      {\tikz\node[inner sep=0pt, opacity=1]{\textcolor{black!#2}{\strut\fadefrom{#1}}};}%
      {\tikz\node[inner sep=0pt, opacity=1]{%
      \textcolor{black!\antitwo}{\strut\fadeto{#1}}};}%
      {O}{c}{F}{F}{L}%
  \fi%
}
%%%
\usepackage{ifthen}
\newcounter{tmpcounter}
\newlength\critlength
\newlength\tmplength
\newcount\mynum
\newcount\myden
\makeatletter
\newcommand\FadeAfter[1]{%
  \critlength=#1\relax%
  \def\cumstring{}\fahelp{#1}{#2}}
\newcommand\fahelp[1]{\fahelper#2 \relax\relax}
\def\fahelper#1 #2\relax{%
  \global\protected@edef\cumstring{\cumstring#1\ }%
  \setbox0=\hbox{\cumstring}%
  \tmplength=.01\critlength\relax%
  \mynum=\wd0\relax%
  \myden=\tmplength\relax%
  \divide\mynum by\myden%
  \setcounter{tmpcounter}{\numexpr100-\the\mynum}%
  \ifnum\thetmpcounter<0\setcounter{tmpcounter}{0}\fi%
  \fadehelperB{\thetmpcounter}#1\relax\ %
    \ifx\relax#2\relax\else\fahelp{\critlength}{#2\relax}\fi%
}
\def\fadehelperB#1#2#3\relax{%
  \fade{#2}{#1}\ifx\relax#3\relax\else\fadehelperB{#1}#3\relax\fi%
}
\makeatother
\parskip 1ex
\begin{document}
\sloppypar
\FadeAfter{10in}{%
Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.}

\def\fadefrom{\ttfamily}
\def\fadeto{\fontfamily{pcr}\selectfont}
\FadeAfter{24in}{%
Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.}

\def\fadefrom{}
\def\fadeto{\fontfamily{ppl}\selectfont}
\FadeAfter{60in}{%
But, in a larger sense, we can not dedicate {{---}} we can not consecrate {{---}} we can not hallow {{---}} this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us {{---}} that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion {{---}} that we here highly resolve that these dead shall not have died in vain {{---}} that this nation, under God, shall have a new birth of freedom {{---}} and that government of the people, by the people, for the people, shall not perish from the earth.}
\end{document}
  1. The 1st paragraph fades from roman to sans font of CM.

  2. The 2nd paragraph fades from CM \ttfamily to the PCR (Courier) font.

  3. The 3rd paragraph fades from CM roman to Palatino roman.

enter image description here

Below, I try it with

\newcommand\fadefrom{\edef\tmp{\the\numexpr\antitwo/3\relax}%
  \ifnum\tmp<10\edef\tmp{0\tmp}\fi%
  \scalebox{1.\tmp}[1]}
\newcommand\fadeto{\edef\tmp{\the\numexpr\antitwo/2\relax}%
  \ifnum\tmp<10\edef\tmp{0\tmp}\fi%
  \sffamily\scalebox{1.\tmp}[1]}

I can achieve progressive stretching of the result.

enter image description here

Zoom:

enter image description here

APPROACH 2

By replacing the \fadehelperB macro, and using cool things like Bruno's \slantbox (Shear transform a "box") and Malipivo's pdf specials (TikZ: halo around text?), I can produce a result that does not involve overlaid fonts. However, it does not represent a true transformation between two arbitrary fonts. Rather, it simultaneously and continuously transforms a single font in 3 ways:

  1. changes the horizontal stretch;

  2. changes the font weight; and

  3. changes the font slant

In the example below, the font outline thickness (a pdfliteral parameter) changes from 0.66 to 0; the horizontal stretch varies from 1.75 to 1; and the slant varies from 0.25 to 0.

\documentclass{article}
\usepackage{xcolor,tikz}
%%%
\usepackage{ifthen}
\newcounter{tmpcounter}
\newlength\critlength
\newlength\tmplength
\newcount\mynum
\newcount\myden
\makeatletter
\newcommand\FadeAfter[2]{%
  \critlength=#1\relax%
  \def\cumstring{}\fahelp{#1}{#2}}
\newcommand\fahelp[2]{\fahelper#2 \relax\relax}
\def\fahelper#1 #2\relax{%
  \global\protected@edef\cumstring{\cumstring#1\ }%
  \setbox0=\hbox{\cumstring}%
  \tmplength=.01\critlength\relax%
  \mynum=\wd0\relax%
  \myden=\tmplength\relax%
  \divide\mynum by\myden%
  \setcounter{tmpcounter}{\numexpr100-\the\mynum}%
  \ifnum\thetmpcounter<1\setcounter{tmpcounter}{1}\fi%
  \fadehelperB{\thetmpcounter}#1\relax\ %
    \ifx\relax#2\relax\else\fahelp{\critlength}{#2\relax}\fi%
}
\def\fadehelperB#1#2\relax{%
  \def\tmp{\the\numexpr2*#1/3\relax}% FONT OUTLINE THICKNESS VARIES FROM .66 TO 0
  \ifnum\tmp<1\relax\def\tmp{1}\fi%
  \ifnum\tmp<10\relax\def\thickness{.0\tmp}\else\def\thickness{.\tmp}\fi%
  \edef\tmp{\the\numexpr3*#1/4\relax}% H-STRETCH VARIES FROM 1.75 TO 1
  \ifnum\tmp<10\edef\tmp{0\tmp}\fi%
  \edef\tmpC{\the\numexpr#1/4\relax}% SLANT VARIES FROM .25 TO 0
  \ifnum\tmpC<10\edef\tmpC{0\tmpC}\fi%
  \scalebox{1.\tmp}[1]{\slantbox[.\tmpC]{\outline{#2}}}}
%%% MALIPIVO's PDF SPECIAL TO CHANGE FONT OUTLINE THICKNESS/COLOR
% https://tex.stackexchange.com/questions/18472/tikz-halo-around-text/169549#169549
\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%
}
\makeatother
\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
}
\bordercolor{black}
\fillcolor{black}
%%% BRUNO's \slantbox
% https://tex.stackexchange.com/questions/63179/shear-transform-a-box/63188#63188
\newsavebox\foobox
\newcommand{\slantbox}[2][.2]{\mbox{%
        \sbox{\foobox}{#2}%
        \hskip\wd\foobox
        \pdfsave
        \pdfsetmatrix{1 0 #1 1}%
        \llap{\usebox{\foobox}}%
        \pdfrestore
}}
%%%
\parskip 1ex
\begin{document}
\sloppypar
\FadeAfter{10in}{%
Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.}

\FadeAfter{24in}{%
Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.}

\FadeAfter{60in}{%
But, in a larger sense, we can not dedicate {{---}} we can not consecrate {{---}} we can not hallow {{---}} this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us {{---}} that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion {{---}} that we here highly resolve that these dead shall not have died in vain {{---}} that this nation, under God, shall have a new birth of freedom {{---}} and that government of the people, by the people, for the people, shall not perish from the earth.}
\end{document}

enter image description here

  • I think the font needs to change mid paragraph via morphing. Letter by letter random font switches might be useful here I guess – percusse Sep 23 '16 at 14:26
  • @percusse I fully understand this is a poor man's imitation. I will note that. – Steven B. Segletes Sep 23 '16 at 14:28
  • 3
    Unbelievable! +10 if I could. So only +1. – Sigur Sep 24 '16 at 2:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy