16

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/

enter image description here

0

2 Answers 2

15

with thanks to

How to put color gradient to "Desired Text Only"

enter image description here

\documentclass{article}
\usepackage{lipsum}


\usepackage{tikz}
\usetikzlibrary{fadings,patterns}
\begin{document}

\newcommand\tikzsection[1]{%
  \begin{tikzfadingfrompicture}[name=tikzsection]
    \node [text=white] {#1};
  \end{tikzfadingfrompicture}
    \begin{tikzpicture}
      \node [text=white,inner sep=0pt,outer sep=0pt] (textnode) {#1};
      \shade[path fading=tikzsection,fit fading=false,left color=\lcolor,right color=\rcolor]
      (textnode.south west) rectangle (textnode.north east);
    \end{tikzpicture}%
}

\makeatletter
\setbox1=\vbox{}


\def\zcolor{red}

\setbox2\vbox{\def\write#1#2{}%
\section{Grr dasadsa}
\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}

A modified colour cycle closer to the image added to the question could be to add

\newcount\colorcycle

to the preamble, then modify the box nodetype code to look like:

\ifnum\lastnodetype=1
\ifcase\colorcycle
\gdef\lcolor{red}\gdef\rcolor{black}\or
\gdef\lcolor{black}\gdef\rcolor{red}\or
\gdef\lcolor{blue}\gdef\rcolor{black}\or
\gdef\lcolor{black}\gdef\rcolor{blue}\global\colorcycle\m@ne\fi
\global\advance\colorcycle\@ne
\global\setbox3\lastbox
\global\setbox1\vbox{%
\hbox{\tikzsection{\copy\thr@@}}%
\unvbox1}%
\fi

enter image description here

8
  • 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.
    – jub0bs
    Sep 6, 2013 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. Sep 6, 2013 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 Sep 6, 2013 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... Sep 11, 2013 at 4:11
  • 1
    @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. Sep 11, 2013 at 8:17
12

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>]
  ... ... ...
\stopbeegradients

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
\stopbeegradients

\startbeegradients [red-green-blue]
  \input knuth
\stopbeegradients

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

\startbeegradients [blackwhite]
  \input knuth
\stopbeegradients

foo bar baz       %% <- no gradient

\startbeegradients
  \input knuth    %% <- black and white again
\stopbeegradients

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

\input luaotfload.sty
\input beegradients.tex

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

\definegradientgroup [mygradients][
  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,
]

\definegradientgroup     [blackwhite][0x000000, 0xFFFFFF]
\definegradientgroup [red-green-blue][255*0*0, 0*255*0, 0*0*255]
\definegradientgroup            [red][255*0*0, 0*0*0]
\definegradientgroup          [green][0*100*0, 0*255*0]
\definegradientgroup           [blue][0*0*20, 0*0*210]

\input knuth

\startbeegradients [mygradients]    \input knuth \stopbeegradients
\startbeegradients [blackwhite]     \input knuth \stopbeegradients
\startbeegradients [red-green-blue] \input knuth \stopbeegradients
\startbeegradients [red]            \input knuth \stopbeegradients
\startbeegradients [green]          \input knuth \stopbeegradients
\startbeegradients [blue]           \input knuth \stopbeegradients

\bye

Result:

Colorful Plain TeX document

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

\documentclass {scrartcl}
\usepackage {fontspec} %% this loads luaotfload as well
\setmainfont {Antykwa Poltawskiego}
\input beegradients.tex

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

\begin {document}
  \startbeegradients [red-green-blue]
    \input knuth
  \stopbeegradients
\end {document}

Which leads to this colorful document:

Colorful Latex document

For texlive 2016 see this post: https://tex.stackexchange.com/a/321962/90087

16
  • 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... Sep 7, 2013 at 21:13
  • @mattharrison your Luaotfload is probably too old. What TeX distribution are you using? Sep 7, 2013 at 21:18
  • luatex --version This is LuaTeX, Version beta-0.70.2-2012091206 (TeX Live 2012/Debian) Sep 7, 2013 at 21:27
  • @mattharrison Yes, definitely too old. You need at least texlive 2013 (you cannot update only luaotfload since it won’t work with Luatex < 0.75). Sep 7, 2013 at 21:35
  • 1
    I'm having a bit of a problem with this and texlive 2016, testing using the lualatex example. This error is popping up Undefined control sequence \RequireLuaModule Missing \begin{document}. \RequireLuaModule {b Undefined control sequence \startbeegradients Use of \startbeegradientsindeed doesn't match its definition \startbeegradients Too many }'s \startbeegradients Should I give up and install texlive 2015 instead?
    – A Feldman
    Jul 16, 2016 at 3:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .