3

This is a follow up question from Box highlighting of text with rounded corners (soul-based). The desired end result is a sort of "circled text", as one would do if annotating a text with a pencil.

I answered that question myself, based on Antal Spector-Zabusky's approach in Cool Text Highlighting in LaTeX. The result is cool enough, but one important limitation is that it does not allow for page breaks. It doesn't because the approach relies on soul for providing coordinates and lets tikz do all the drawing. That was needed in Antal's answer because the desired irregularity of the path, to make sense in a drawing, depended on the decorations from tikz.

Well, I'm looking for something "less cool" and would be satisfied with straight lines above and below the text. And for that, I could rely on soul rather than tikz to draw them, thus retaining page breaking capabilities. And then, use tikz to draw the corners only.

I started from the same idea, but tried it from scratch, based on the soul driver for \ul. The code below gets close, but not quite. I cannot convince \SOUL@everyspace to draw the line above as well.

The crux of the matter seems to lie in:

\def\SOUL@tceveryspace#1{%
  \SOUL@ulcolor{
    #1%
    \SOUL@tcleaders
    \hskip\spaceskip
  }%
  \null
}

where \SOUL@tcleaders does the actual drawing with an \hrule:

\def\SOUL@tcleaders{%
  \leaders\hrule\@depth\SOUL@tcdp\@height\SOUL@tcht\relax
}

Is there a way to draw both (bottom and top) hrules in this step?

The full code is:

\documentclass[12pt]{scrartcl}
\usepackage{soulutf8}
\usepackage{tikz}

\usetikzlibrary{calc,decorations.pathmorphing}

\newlength\LineWidth
\setlength\LineWidth{1pt}

\newlength\baseliney
\setlength\baseliney{.45ex}

\newlength\heighty

\newcommand\opac{0.35}

\colorlet{HLcolor}{gray}

\setul{.325ex}{\LineWidth}
\colorlet{ulcolor}{gray!35}
\setulcolor{ulcolor}

\makeatletter

\newdimen\SOUL@tcdp
\newdimen\SOUL@tcht
\newdimen\SOUL@tchdp
\newdimen\SOUL@tchht

\def\SOUL@tcleaders{%
  \leaders\hrule\@depth\SOUL@tcdp\@height\SOUL@tcht\relax
}
\def\SOUL@tcheaders{%
  \leaders\hrule\@depth\SOUL@tchdp\@height\SOUL@tchht\relax
}

\def\SOUL@tcunderline#1{{%
    \setbox\z@\hbox{#1}%
    \dimen@=\wd\z@
    \dimen@i=\SOUL@uloverlap
    \advance\dimen@2\dimen@i
    \rlap{%
      \null
      \kern-\dimen@i
      \SOUL@ulcolor{\SOUL@tcleaders\hskip\dimen@}%
    }%
    \rlap{%
      \null
      \kern-\dimen@i
      \SOUL@ulcolor{\SOUL@tcheaders\hskip\dimen@}%
    }%
    \unhcopy\z@
  }}

\def\SOUL@tcpreamble{%
  \setlength{\heighty}{\f@size pt}%
  \SOUL@tcdp=\SOUL@uldepth
  \SOUL@tcht=-\SOUL@tcdp
  \advance\SOUL@tcdp\SOUL@ulthickness
  \SOUL@tchdp=-\heighty
  \advance\SOUL@tchdp\SOUL@tcdp
  \advance\SOUL@tchdp-\SOUL@ulthickness
  \SOUL@tchht=-\SOUL@tchdp
  \advance\SOUL@tchdp\SOUL@ulthickness
  \spaceskip\SOUL@spaceskip
  \begin{tikzpicture}[decoration={bent,aspect=.3}, overlay]
    \draw[decorate,HLcolor,line width=\LineWidth,opacity=\opac]  ($(0,-\baseliney)$) -- ($(0,-\baseliney+\heighty)$) ;
  \end{tikzpicture}%
}
\def\SOUL@tceverysyllable{%
  \SOUL@tcunderline{%
    \the\SOUL@syllable
    \SOUL@setkern\SOUL@charkern
  }%
}
\def\SOUL@tceveryspace#1{%
  \SOUL@ulcolor{
    #1%
    \SOUL@tcleaders
    \hskip\spaceskip
  }%
  \null
}
\def\SOUL@tceveryhyphen{%
  \discretionary{%
    \unkern
    \SOUL@tcunderline{%
      \SOUL@setkern\SOUL@hyphkern
      \SOUL@sethyphenchar
    }%
  }{}{}%
}
\def\SOUL@tceveryexhyphen#1{%
  \SOUL@setkern\SOUL@hyphkern
  \SOUL@tcunderline{#1}%
  \discretionary{}{}{%
    \SOUL@setkern\SOUL@charkern
  }%
}
\def\SOUL@tcpostamble{%
  \begin{tikzpicture}[decoration={bent,aspect=.3}, overlay]
    \draw[decorate,HLcolor,line width=\LineWidth,opacity=\opac]  ($(0,-\baseliney+\heighty)$) -- ($(0,-\baseliney)$) ;
  \end{tikzpicture}%
}
\def\SOUL@tcsetup{%
  \SOUL@setup
  \let\SOUL@preamble\SOUL@tcpreamble
  \let\SOUL@everysyllable\SOUL@tceverysyllable
  \let\SOUL@everyspace\SOUL@tceveryspace
  \let\SOUL@everyhyphen\SOUL@tceveryhyphen
  \let\SOUL@everyexhyphen\SOUL@tceveryexhyphen
  \let\SOUL@postamble\SOUL@tcpostamble
}
\DeclareRobustCommand*\textcirc{\SOUL@tcsetup\SOUL@}

\makeatother


\begin{document}

\vspace*{15cm}

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus
elit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur
dictum gravida mauris. \textcirc{Nam arcu libero, nonummy eget,
  consectetuer id, vulputate a, magna.  Donec vehicula augue eu
  neque. Pellentesque habitant morbi tristique senectus et netus et
  malesuada fames ac turpis egestas.} Mauris ut leo. Cras viverra
metus rhoncus sem. Nulla et lectus vestibulum urna fringilla
ultrices. Phasellus eu tellus sit amet tortor gravida
placerat. Integer sapien est, iaculis in, pretium quis, viverra ac,
nunc. Praesent eget sem vel leo ultrices bibendum. Aenean
faucibus. Morbi dolor nulla, malesuada eu, pulvinar at, mollis ac,
nulla. Curabitur auctor semper nulla. \textcirc{Donec varius orci}
eget risus. Duis nibh mi, congue eu, accumsan eleifend, sagittis quis,
diam. Duis eget orci sit amet orci dignissim rutrum.  Nam dui ligula,
\textcirc{fringilla a, euismod sodales, sollicitudin vel}, wisi. Morbi
auctor lorem non justo. Nam lacus libero, pretium at, lobortis vitae,
ultricies et, tellus. \textcirc{Donec aliquet, tortor sed accumsan
  bibendum, erat ligula aliquet magna, vitae ornare odio metus a mi.}
Morbi ac orci et nisl hendrerit mollis. Suspendisse ut massa. Cras nec
ante. \ul{Pellentesque a nulla.} \textcirc{Cum sociis natoque
  penatibus et magnis dis parturient montes, nascetur ridiculus mus.}
Aliquam tincidunt urna. Nulla ullamcorper vestibulum
turpis. Pellentesque cursus luctus mauris.

\end{document}

The result thus far is:

enter image description here

enter image description here

That is, everything is in place, except the lines above the spaces. Any ideas on how to get them?

  • I certainly do not understand you code, but you're saying that you "use tikz to draw the corners only". I am wondering what's wrong with connecting these corners with lines (if you are using TikZ anyway). – user121799 Apr 17 '18 at 15:42
  • @marmot Well, that's what Antal Spector-Zabusky's answer does, but doesn't allow for page breaks (at least as far as the answer lays). This code is based on the definitions of the soul driver for underlining, I just adapted it. – gusbrs Apr 17 '18 at 15:58
  • But can't you just add a line all the way to the boundary of current page text area (tikzpagenode package) in the case of a page break? – user121799 Apr 17 '18 at 16:27
  • @marmot, Mmh, I'm not sure I grasp your idea. But, if I do, we would have to know beforehand the line at which the page break occurs. Otherwise the coordinates to end of the line would have to be supplied from soul. Antal Spector-Zabusky's approach gets this coordinate syllable by syllable with the help of soul. How could we decide on the fly when not to do it and use instead current page text area? Or am I missing something from your suggestion? – gusbrs Apr 17 '18 at 16:41
  • Not necessarily. You could run the line always to either the closing corner or the boundary of current page text area, whatever comes first. One possible way to achieve this is to run a white line from the corners to the boundary of current page text area whenever you issue the closing brackets. – user121799 Apr 17 '18 at 16:57
3

You did all the work already. I only changed \SOUL@tceveryspace (and did not read the rest of the code at all to be honest). The command uses essentially \leaders\hrule\hskip\spaceskip, which means "make a horizontal rule that otherwise behaves like glue of length \spaceskip". In particular that glue allows line breaks and is removed when there is a line break (just like normal spaces do). To have lines above and below, I just used one leader, one negative space to go back to the original place and another leader on top. You can see that everything stretches properly in my first line after \begin{document}.

\documentclass[12pt]{scrartcl}
\usepackage{soulutf8}
\usepackage{tikz}

\usetikzlibrary{calc,decorations.pathmorphing}

\newlength\LineWidth
\setlength\LineWidth{1pt}

\newlength\baseliney
\setlength\baseliney{.45ex}

\newlength\heighty

\newcommand\opac{0.35}

\colorlet{HLcolor}{gray}

\setul{.325ex}{\LineWidth}
\colorlet{ulcolor}{gray!35}
\setulcolor{ulcolor}

\makeatletter

\newdimen\SOUL@tcdp
\newdimen\SOUL@tcht
\newdimen\SOUL@tchdp
\newdimen\SOUL@tchht

\def\SOUL@tcleaders{%
  \leaders\hrule\@depth\SOUL@tcdp\@height\SOUL@tcht\relax
}
\def\SOUL@tcheaders{%
  \leaders\hrule\@depth\SOUL@tchdp\@height\SOUL@tchht\relax
}

\def\SOUL@tcunderline#1{{%
    \setbox\z@\hbox{#1}%
    \dimen@=\wd\z@
    \dimen@i=\SOUL@uloverlap
    \advance\dimen@2\dimen@i
    \rlap{%
      \null
      \kern-\dimen@i
      \SOUL@ulcolor{\SOUL@tcleaders\hskip\dimen@}%
    }%
    \rlap{%
      \null
      \kern-\dimen@i
      \SOUL@ulcolor{\SOUL@tcheaders\hskip\dimen@}%
    }%
    \unhcopy\z@
  }}

\def\SOUL@tcpreamble{%
  \setlength{\heighty}{\f@size pt}%
  \SOUL@tcdp=\SOUL@uldepth
  \SOUL@tcht=-\SOUL@tcdp
  \advance\SOUL@tcdp\SOUL@ulthickness
  \SOUL@tchdp=-\heighty
  \advance\SOUL@tchdp\SOUL@tcdp
  \advance\SOUL@tchdp-\SOUL@ulthickness
  \SOUL@tchht=-\SOUL@tchdp
  \advance\SOUL@tchdp\SOUL@ulthickness
  \spaceskip\SOUL@spaceskip
  \begin{tikzpicture}[decoration={bent,aspect=.3}, overlay]
    \draw[decorate,HLcolor,line width=\LineWidth,opacity=\opac]  ($(0,-\baseliney)$) -- ($(0,-\baseliney+\heighty)$) ;
  \end{tikzpicture}%
}
\def\SOUL@tceverysyllable{%
  \SOUL@tcunderline{%
    \the\SOUL@syllable
    \SOUL@setkern\SOUL@charkern
  }%
}
\def\SOUL@tceveryspace#1{%
  \SOUL@ulcolor{
    #1%
    \SOUL@tcleaders
    \hskip\spaceskip
    \hskip-\spaceskip
    \SOUL@tcheaders
    \hskip\spaceskip
  }%
  \null
}
\def\SOUL@tceveryhyphen{%
  \discretionary{%
    \unkern
    \SOUL@tcunderline{%
      \SOUL@setkern\SOUL@hyphkern
      \SOUL@sethyphenchar
    }%
  }{}{}%
}
\def\SOUL@tceveryexhyphen#1{%
  \SOUL@setkern\SOUL@hyphkern
  \SOUL@tcunderline{#1}%
  \discretionary{}{}{%
    \SOUL@setkern\SOUL@charkern
  }%
}
\def\SOUL@tcpostamble{%
  \begin{tikzpicture}[decoration={bent,aspect=.3}, overlay]
    \draw[decorate,HLcolor,line width=\LineWidth,opacity=\opac]  ($(0,-\baseliney+\heighty)$) -- ($(0,-\baseliney)$) ;
  \end{tikzpicture}%
}
\def\SOUL@tcsetup{%
  \SOUL@setup
  \let\SOUL@preamble\SOUL@tcpreamble
  \let\SOUL@everysyllable\SOUL@tceverysyllable
  \let\SOUL@everyspace\SOUL@tceveryspace
  \let\SOUL@everyhyphen\SOUL@tceveryhyphen
  \let\SOUL@everyexhyphen\SOUL@tceveryexhyphen
  \let\SOUL@postamble\SOUL@tcpostamble
}
\DeclareRobustCommand*\textcirc{\SOUL@tcsetup\SOUL@}

\makeatother


\begin{document}

\vspace*{15cm}

\hbox to 200pt{Lorem ipsum \textcirc{dolor sit} amet}

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus
elit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur
dictum gravida mauris. \textcirc{Nam arcu libero, nonummy eget,
  consectetuer id, vulputate a, magna.  Donec vehicula augue eu
  neque. Pellentesque habitant morbi tristique senectus et netus et
  malesuada fames ac turpis egestas.} Mauris ut leo. Cras viverra
metus rhoncus sem. Nulla et lectus vestibulum urna fringilla
ultrices. Phasellus eu tellus sit amet tortor gravida
placerat. Integer sapien est, iaculis in, pretium quis, viverra ac,
nunc. Praesent eget sem vel leo ultrices bibendum. Aenean
faucibus. Morbi dolor nulla, malesuada eu, pulvinar at, mollis ac,
nulla. Curabitur auctor semper nulla. \textcirc{Donec varius orci}
eget risus. Duis nibh mi, congue eu, accumsan eleifend, sagittis quis,
diam. Duis eget orci sit amet orci dignissim rutrum.  Nam dui ligula,
\textcirc{fringilla a, euismod sodales, sollicitudin vel}, wisi. Morbi
auctor lorem non justo. Nam lacus libero, pretium at, lobortis vitae,
ultricies et, tellus. \textcirc{Donec aliquet, tortor sed accumsan
  bibendum, erat ligula aliquet magna, vitae ornare odio metus a mi.}
Morbi ac orci et nisl hendrerit mollis. Suspendisse ut massa. Cras nec
ante. \ul{Pellentesque a nulla.} \textcirc{Cum sociis natoque
  penatibus et magnis dis parturient montes, nascetur ridiculus mus.}
Aliquam tincidunt urna. Nulla ullamcorper vestibulum
turpis. Pellentesque cursus luctus mauris.

\end{document}
  • Oh, that's beautiful! Thank you very much! I had tried to retreat with a \kern there, but somehow it didn't work. As I mentioned to marmot in the chat, soul's code is way out of my league, it's no wonder I was stumbling. Thanks! – gusbrs Apr 18 '18 at 2:20
  • 1
    \kern, contrarily to \hskip, does not allow breaks, so TeX would treat the combination of a leader, a kern, and a leader as somewhat similar to a space, a letter, and a space. Instead, what I do gives a space, a space, a space, all of which are deleted when there is a line-break. – Bruno Le Floch Apr 18 '18 at 4:40
  • I wouldn't have guessed that... I suppose it's time I start my studies on "The TeX Book", ain't it? :) – gusbrs Apr 18 '18 at 10:03

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.