I've looked at the demo of Beeline reader and would like to test it out on a physical version of my books, which are done in LaTeX. I'm wondering if it would even be possible.

Beeline reader takes online test a puts a slight gradient on the letters for a single line of text. On the next line it reverses the direction of the gradient. The idea being that it helps tracking text and improves speed of reading.

Any hints or suggestions as to how to do this in LaTeX?

What follows is an example taken from http://www.beelinereader.com/

-
Could you post an image of the effect that you want to see. The demo does not load for me. – Aditya Sep 6 '13 at 15:17

with thanks to

How to put color gradient to "Desired Text Only"

\documentclass{article}
\usepackage{lipsum}

\usepackage{tikz}
\begin{document}

\newcommand\tikzsection[1]{%
\node [text=white] {#1};
\begin{tikzpicture}
\node [text=white,inner sep=0pt,outer sep=0pt] (textnode) {#1};
(textnode.south west) rectangle (textnode.north east);
\end{tikzpicture}%
}

\makeatletter
\setbox1=\vbox{}

\def\zcolor{red}

\setbox2\vbox{\def\write#1#2{}%
\lipsum\par

% at this point we are at the end of box 2 now
% loop backwards up the vertical list copying glue and penalties
% but modifying boxesto add the prefix.
\loop
%
% an e-tex primitive that reports the last item in the vertical list.
% type 1 is a box, so remove the box (a lien of text) and then
% put into box 1 a box that is this box together with the prefix which
% was saved in box 0
\ifnum\lastnodetype=1
\ifx\rcolor\zcolor
\gdef\lcolor{red}\gdef\rcolor{blue}%
\else
\gdef\lcolor{blue}\gdef\rcolor{red}%
\fi
\global\setbox3\lastbox
\global\setbox1\vbox{%
\hbox{\tikzsection{\copy\thr@@}}%
\unvbox1}%
\fi
%
% type 11 is glue so remove it from this list and add
% equivalent glue to box 1
\ifnum\lastnodetype=11
\skip0\lastskip\unskip
\global\setbox1\vbox{\vskip\skip0\unvbox1}%
\fi
%
% same for penalty
\ifnum\lastnodetype=13
\count0\lastpenalty\unpenalty
\global\setbox1\vbox{\penalty\count0 \unvbox1}%
\fi
%
% other node types are not handled here: either they won't happen
% or they can't be removed anyway so would break the loop \special
% for example would be bad.
%
% -1 means the vertical list is empty: we have reached the top of the box.
\ifnum\lastnodetype=-1
\else
\repeat}%

% Tip the modified box back onto the main list for the page, unbox
% it so that page breaking may still happen (if it could happen in the
% original context).
\unvbox1

\end{document}

-
That's great, David. However, beeline seems to use three colours. I think the rationale may be that, if only two colours are used, there is a greater risk of skipping a line when reading the middle of a block of text (because the colour of two successive lines is the same in the middle). That risk is somewhat reduced with three colours. – Jubobs Sep 6 '13 at 16:30
@Jubobs ah you mean each row just has two colours but you cycle a-b b-c c-a ? that is easily done just modify the \ifx block in the niddle to cycle the two colour macros. – David Carlisle Sep 6 '13 at 16:37
@Jubobs oh no the image added to the question goes black-red red-black black-blue blue-black but again it's just how you switch lcolor and rcolor macros – David Carlisle Sep 6 '13 at 16:41
Thanks for your answer, I tried to apply this to my book and pegged the CPU for a couple hours before I killed it... – matt harrison Sep 11 '13 at 4:11
@mattharrison It might take a fraction longer than normal but if it takes a lot longer then it is in an infinite loop almost certainly because there is a non-removable item such as a \special or a write on the main vertical list. (Note I disabled \write in the above) You can apply the system more locally on a per-paragraph basis, and also put in a test to check for non-removable items (you could not recover cleanly but at least you could abort the loop) or to avoid the restriction on not being able to remove unremovable items you need to leave tex, hence the luatex version in the other answer. – David Carlisle Sep 11 '13 at 8:17

That’s a wonderful use case for Luatex! (In fact, when I read the about the bee colors yesterday I was hoping for this question to pop up on TeX-SE.) So, without further ado, here is the necessary code. This requires Luaotfload, which Latex users do not have to load explicitly if they are using the fontspec package.

The beecolors code is split into a TeX and a Lua file. The Lua part (beegradients.lua) implements a node processor for the post_linebreak_filter callback. The principle is quite simple: It scans the horizontal lists that constitute a paragraph for glyphs and ligatures which it surrounds with the appropriate PDF color whatsits, recursing into any vlists an hlists it encounters along the way.

The second file (beegradients.tex) contains wrapper macros for defining gradients and toggling the callback. A gradient group is a list of color expressions and can be defined like this:

\definegradientgroup [<name>][<col1>,<col2>, ... ,<coln>]


E.g.

\definegradientgroup [blackwhite][0x000000, 0xFFFFFF]


installs a gradient list consisting of two colors, black and white. Likewise,

\definegradientgroup [red-green-blue][255*0*0, 0*255*0, 0*0*255]


defines a list of three colors, red, green and blue.

These gradient groups can afterwards be referred to by their names. The callback can be activated by means of an environment beegradients:

\startbeegradients [<name>]
... ... ...


Where <name> refers to a previously defined gradient group. E.g., in order to use the groups blackwhite and red-green-blue we defined above:

\startbeegradients [blackwhite]
\input knuth

\input knuth


Without the optional argument, \startbeegradients will choose the last active group.

\startbeegradients [blackwhite]
\input knuth

foo bar baz       %% <- no gradient

\input knuth    %% <- black and white again


Here is a complete example for the Plain format that shows a couple definitions:

\input luaotfload.sty

\font \mainfont = file:Iwona-Regular.otf at 10pt
\mainfont

42*11*242,        %% decimal notation, separated by “*”
83*242*55,
0xf00ba7,         %% hex notation
0x1ec001,
g:23*b:42*r:133,  %% rgb notation, also separated by “*”
b:53*g:184*r:10,
]

\input knuth

\bye


Result:

Of course the code is compatible with Latex, you can load it directly:

\documentclass {scrartcl}
\setmainfont {Antykwa Poltawskiego}

\begin {document}

Thanks for your answer. I'm a LuaTex newbie, but am getting the following error:! LuaTeX error ./beegradients.lua:32: attempt to index local 'nodecodes' (a nil value) stack traceback: ./beegradients.lua:32: in main chunk [C]: in function 'require' ...exlive/texmf-dist/tex/luatex/luatexbase/modutils.lua:52: in function 'requi re_module' <\directlua >:1: in main chunk. \lltxb@requirelua ...xluaescapestring {#2}" \fi )} l.2 I'm at a loss on how to deal with this... – matt harrison Sep 7 '13 at 21:13
luatex --version This is LuaTeX, Version beta-0.70.2-2012091206 (TeX Live 2012/Debian) – matt harrison Sep 7 '13 at 21:27