13

I was recently referred to Cool Text Highlighting in LaTeX for Tikz highlighting-underlining.

I've managed to modify Antal answer to my needs but I can't seem to achieve the following: I'd like the highlight to be drawn on the background of text and not over it, as it is now.

I've prepared a MWE for better explaining what I mean:

\documentclass{minimal}
\usepackage{soul}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathmorphing}

\makeatletter

\newcommand{\defhighlighter}[3][]{%
  \tikzset{every highlighter/.style={color=#2, fill opacity=#3, #1}}%
}

\defhighlighter{yellow}{.5}

\newcommand{\highlight@DoHighlight}{
  \fill [ decoration = {random steps, amplitude=1pt, segment length=15pt}
        , outer sep = -15pt, inner sep = 0pt, decorate
        , every highlighter, this highlighter ]
        ($(begin highlight)+(0,8pt)$) rectangle ($(end highlight)+(0,-3pt)$) ;
}

\newcommand{\highlight@BeginHighlight}{
  \coordinate (begin highlight) at (0,0) ;
}

\newcommand{\highlight@EndHighlight}{
  \coordinate (end highlight) at (0,0) ;
}

\newdimen\highlight@previous
\newdimen\highlight@current

\DeclareRobustCommand*\highlight[1][]{%
  \tikzset{this highlighter/.style={#1}}%
  \SOUL@setup
  %
  \def\SOUL@preamble{%
    \begin{tikzpicture}[overlay, remember picture]
      \highlight@BeginHighlight
      \highlight@EndHighlight
    \end{tikzpicture}%
  }%
  %
  \def\SOUL@postamble{%
    \begin{tikzpicture}[overlay, remember picture]
      \highlight@EndHighlight
      \highlight@DoHighlight
    \end{tikzpicture}%
  }%
  %
  \def\SOUL@everyhyphen{%
    \discretionary{%
      \SOUL@setkern\SOUL@hyphkern
      \SOUL@sethyphenchar
      \tikz[overlay, remember picture] \highlight@EndHighlight ;%
    }{%
    }{%
      \SOUL@setkern\SOUL@charkern
    }%
  }%
  %
  \def\SOUL@everyexhyphen##1{%
    \SOUL@setkern\SOUL@hyphkern
    \hbox{##1}%
    \discretionary{%
      \tikz[overlay, remember picture] \highlight@EndHighlight ;%
    }{%
    }{%
      \SOUL@setkern\SOUL@charkern
    }%
  }%
  %
  \def\SOUL@everysyllable{%
    \begin{tikzpicture}[overlay, remember picture]
      \path let \p0 = (begin highlight), \p1 = (0,0) in \pgfextra
        \global\highlight@previous=\y0
        \global\highlight@current =\y1
      \endpgfextra (0,0) ;
      \ifdim\highlight@current < \highlight@previous
        \highlight@DoHighlight
        \highlight@BeginHighlight
      \fi
    \end{tikzpicture}%
    \the\SOUL@syllable
    \tikz[overlay, remember picture] \highlight@EndHighlight ;%
  }%
  \SOUL@
}
\makeatother

\begin{document}
\highlight[yellow]{The highlight is drawn over the text}

\bigskip
\begin{tikzpicture}
\node[fill=yellow!50]{the highlight is drawn below text};
\end{tikzpicture}
\end{document}

Is it possible to move the highliting below the text as in standard filling for Tikz nodes?

5
  • It would be also OK if the answer from Martin Scharrer (or a completely different approach) is used for highlighting as long as the highlight goes below text.
    – Jansen
    Sep 26, 2014 at 14:30
  • 1
    I think you'll need to mix your code with the one in is-it-possible-to-use-tikz-to-draw-a-background-on-the-printed-page
    – Ignasi
    Sep 26, 2014 at 14:55
  • So the other answer there is no good? You consider the wiggliness crucial?
    – cfr
    Sep 26, 2014 at 21:51
  • @cfr the answer from Martin Scharrer has the same problem (highlight goes over the text), the other answers do not suit my needs because are not done with Tikz (I need the highlight to be drawn by TikZ to add various decorations).
    – Jansen
    Sep 27, 2014 at 12:34
  • @Jansen The wiggliness, then.
    – cfr
    Sep 27, 2014 at 17:07

1 Answer 1

8

With this solution, I leave the OP's solution in place and add another layer in the form of \Ohighlight, in the form of

\newsavebox\tmpbox
\usepackage{tabto}
\newcommand\Ohighlight[2][]{%
  \tabto*{0in}\edef\tmpx{\TabPrevPos}\tabto*{\tmpx}%    SAVES THE CURRENT x POSITION
  \savebox\tmpbox{%                            SETS THE TEXT, STARTING AT x, IN A SAVED MINIPAGE
  \begin{minipage}[b]{\textwidth}
    \tabto*{\tmpx}#2\strut%
  \end{minipage}}%
  {\color{\highlightcolor!0}\highlight[#1]{#2}}%         STEP #1, BELOW
  \vspace*{\dimexpr-\dp\tmpbox-\ht\tmpbox+\dp\strutbox}% STEP #2, BELOW
  \tabto*{\tmpx}#2\unskip\ %                             STEP #3, BELOW
}

which tries to accomplish the following:

1) do the original \highlighting, while making the text the same color as the highlight (aka invisible);

2) back up to the original location (horizontally by way of tabto package) and vertically by way of \vspace on a measured minipage;

3) retype the text, in the clear, atop the prior highlighting, which leaves the page position where it ought to be.

This solution was EDITED when some kerning differences were noted between the output of \highlight and text in the clear. The pre-\highlight is now done in a blank color, to avoid the issue of double-striked text.

This approach will not work across page boundaries. In the MWE, it works across paragraph boundaries, but I imagine that inserted glue on a page could mess that up, unless \raggedbottom were used.

The fact that some kerning issues were noted that prompted an edit to my code leaves open the possibility that for some cases, the \highlight linebreaking would differ from text in the clear, which would obviously represent a failure of the method. Since the issue seemed related to trailing blank spaces, adding an \unskip\ to the final text in the clear (step 3.) seemed to fix the kerning issue, but I won't say that it can't pop up under another guise.

If one wants to check the kerning issue, then edit this line {\color{\highlightcolor!0}\highlight[#1]{#2}}% to {\color{red}\highlight[#1]{#2}}%, which will produce a double-strike of the text. If they don't match up, you will see it there.

\documentclass{minimal}
\usepackage{soul}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathmorphing}

\makeatletter

\newcommand{\defhighlighter}[3][]{%
  \tikzset{every highlighter/.style={color=#2, fill opacity=#3, #1}}%
}

\def\highlightcolor{yellow}
\defhighlighter{\highlightcolor}{.5}

\newcommand{\highlight@DoHighlight}{
  \fill [ decoration = {random steps, amplitude=1pt, segment length=15pt}
        , outer sep = -15pt, inner sep = 0pt, decorate
        , every highlighter, this highlighter ]
        ($(begin highlight)+(0,8pt)$) rectangle ($(end highlight)+(0,-3pt)$) ;
}

\newcommand{\highlight@BeginHighlight}{
  \coordinate (begin highlight) at (0,0) ;
}

\newcommand{\highlight@EndHighlight}{
  \coordinate (end highlight) at (0,0) ;
}

\newdimen\highlight@previous
\newdimen\highlight@current

\DeclareRobustCommand*\highlight[1][]{%
  \tikzset{this highlighter/.style={#1}}%
  \SOUL@setup
  %
  \def\SOUL@preamble{%
    \begin{tikzpicture}[overlay, remember picture]
      \highlight@BeginHighlight
      \highlight@EndHighlight
    \end{tikzpicture}%
  }%
  %
  \def\SOUL@postamble{%
    \begin{tikzpicture}[overlay, remember picture]
      \highlight@EndHighlight
      \highlight@DoHighlight
    \end{tikzpicture}%
  }%
  %
  \def\SOUL@everyhyphen{%
    \discretionary{%
      \SOUL@setkern\SOUL@hyphkern
      \SOUL@sethyphenchar
      \tikz[overlay, remember picture] \highlight@EndHighlight ;%
    }{%
    }{%
      \SOUL@setkern\SOUL@charkern
    }%
  }%
  %
  \def\SOUL@everyexhyphen##1{%
    \SOUL@setkern\SOUL@hyphkern
    \hbox{##1}%
    \discretionary{%
      \tikz[overlay, remember picture] \highlight@EndHighlight ;%
    }{%
    }{%
      \SOUL@setkern\SOUL@charkern
    }%
  }%
  %
  \def\SOUL@everysyllable{%
    \begin{tikzpicture}[overlay, remember picture]
      \path let \p0 = (begin highlight), \p1 = (0,0) in \pgfextra
        \global\highlight@previous=\y0
        \global\highlight@current =\y1
      \endpgfextra (0,0) ;
      \ifdim\highlight@current < \highlight@previous
        \highlight@DoHighlight
        \highlight@BeginHighlight
      \fi
    \end{tikzpicture}%
    \the\SOUL@syllable
    \tikz[overlay, remember picture] \highlight@EndHighlight ;%
  }%
  \SOUL@
}
\makeatother

\newsavebox\tmpbox
\usepackage{tabto}
\newcommand\Ohighlight[2][]{%
  \tabto*{0in}\edef\tmpx{\TabPrevPos}\tabto*{\tmpx}%
  \savebox\tmpbox{%
  \begin{minipage}[b]{\textwidth}
    \tabto*{\tmpx}#2\strut%
  \end{minipage}}%
  {\color{\highlightcolor!0}\highlight[#1]{#2}}%
  \vspace*{\dimexpr-\dp\tmpbox-\ht\tmpbox+\dp\strutbox}%
  \tabto*{\tmpx}#2\unskip\ %
}
\textwidth=5in

\begin{document}
\highlight{The original highlight is drawn over the text.
The original definition works over... 

Multi paragraphs, so my fix should try to as well.}

\bigskip
\begin{tikzpicture}
\node[fill=yellow!50]{with tikz, the highlight is drawn below text but not fancy};
\end{tikzpicture}

Now here is my fix. \Ohighlight{The highlight is drawn under the text}
Does it work multiline?
\Ohighlight[yellow]{The highlight is drawn under the text The highlight is drawn under the text The highlight is drawn under the text The highlight is drawn under the text

A new paragraph}
And more...
\Ohighlight{short}

\end{document}

enter image description here

The image below shows a zoom.

enter image description here

0

You must log in to answer this question.

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