LaTeX 中的酷炫文本突出显示

LaTeX 中的酷炫文本突出显示

LaTeX 有soul。当然有 ConTeXt,有漂亮的“sharpie”突出显示,您可以在文本下方免费添加甜蜜的高光!

来自 randomdeterminism.wordpress.com

在图示的示例中,您可以看到突出显示不仅突出显示,而且还具有很酷的边缘,看起来很棒,您甚至可以闻到烟味!这位大胆的作者说,他将在另一篇文章中展示如何做到这一点;这篇文章只展示了如何放置一个直的黄色框。但是,大概可以在 ConTeXt 中使用酷炫的框进行文字换行突出显示。

对我来说,麻烦的是,考虑到文档的状态和变化,进入 ConTeXt 世界现在是一个艰难的攀登,所以我需要继续使用 LaTeX。但是真实的问题是,现在我不能没有那张照片中看起来有机的精彩亮点!

正如我所说,使用灵魂包可以轻松实现普通的非有机亮点:

\hl{Some awesome text that word wraps fine.}

它只是用页面上的直线来嘲弄我。因此,如果我放弃自动换行,我可以使用 PGF/TiKz 并创建以下宏:

\newcommand\hl[1]{%
    \tikz[baseline,%
      decoration={random steps,amplitude=1pt,segment length=15pt},%
      outer sep=-15pt, inner sep = 0pt%
    ]%
   \node[decorate,rectangle,fill=navcolor,anchor=text]{#1\xspace};%
}%

这会创建如下内容:

我的 TiKz 荧光笔的外观图片

现在,我的颜色太暗,随机性需要调整,但您会发现可以实现类似的效果。

我的问题是我对 TeX 了解不够,无法深入研究 Soul 包并添加它急需的 TiKz/PGF 优点。所以,我把这个问题留给你们了。有人想解决这个问题吗?

或者它只是另一个遥不可及的果实,必须等到 ConTeXt 稳定下来才能得到?

答案1

令我惊讶的是,通过将 TikZ 和 soul 结合起来,这是可行的。我不认为我喜欢它的外观(尽管每个人都有自己的看法),但这是一个有趣的挑战。这个想法是使用 TikZ 绘制必要的框最多换行,然后在新的一行上重新启动每个框。但是怎么做呢?好吧,事实证明,soul 的工作原理是在每个可能的连字符点(它称之为“音节”,我发现这种术语滥用很烦人)后插入内容——重要的是,这包括单词的开头和结尾。我们唯一一次看到换行符是在连字符点之后!这很好:我们将使用 soul 在每个音节中断处插入一个 TikZ 节点,然后将它们绘制在一起。为此,我们使用 TikZ 的remember pictureoverlay选项;前者使您能够从外部引用带标签的图片中的节点,而后者使图片不占用空间。

为了实现这一点,我们用两个“标记”(TikZ 图片)包围每个连字单元。“开始”标记检查它是否在新行上;如果是,它会从最后记录的开始位置到最后记录的结束位置绘制突出显示的矩形,然后记录新的开始位置。“停止”标记只记录新的停止位置。我们还必须确保在连字点处,停止位置位于连字符之后。当然,我们用起始位置和停止位置包围整个图片。请注意,由于机制原因remember picture,您必须编译文档两次。

以下是一份突出显示不清晰的工作文档:

\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}
  Lorem ipsum \highlight{dolor sit amet, consectetur adipis-icing elit, sed do
eiusmod tempor} incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation \highlight[red]{ullamco $laboris$ nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit} in
voluptate velit esse cillum dolore eu fugiat nulla pariatur.  Excepteur sint
occaecat \highlight[green, draw=blue]{cupidatat non proident,
suntinculpaquiofficiadeseruntmollitanimidestlaborum.
Loremipsumdolorsitametconsecteturadipisicingelitseddoeiusmodtemporincididuntutlabore-etdoloremagnaaliqua.}
I suppose I could write some more text here.
\end{document}

这将产生以下输出:

带有粗糙高光的 Lipsum 文本。

有两种格式化模式:\defhighlighter[misc]{color}{opacity},将填充颜色设置为color,将填充不透明度设置为opacity,并使用every highlighter和选项为每个高亮块(通过 )设置样式misc。其次,对于特定的高亮文本块,您可以使用\highlight[tikz-opts]{...}本地设置选项。以上代码均演示了这些。

目前有四个注意事项。第一,这会将突出显示文本中的每个音节中断写入辅助文件中的一行,此外,每个音节的开头、结尾和(实际或插入的)连字符后的每个换行符都会写入一行。例如,示例文档向我的辅助文件中写入了 222 行。这对您来说可能是问题,也可能不是问题,但我不确定如何改善它。第二,如果让突出显示延伸到分页符,就会发生奇怪的事情。(虽然我可能能够修复这个问题……)第三,我没有看到在背景中绘制突出显示的方法。(因为它绘制得太晚,环境pgfonlayer不起作用。)这就是文本看起来褪色的原因。如果您不喜欢这样,您可以调整不透明度值,但我不知道如何避免它(建议?)。第四,我猜测了字体的高度,因为虽然我认为这应该是 TeX 某处的尺寸,但我不知道在哪里(再次,有什么建议吗?)。

答案2

我看不出你提供的图片和

\documentclass{article}
\usepackage[width=5.05cm]{geometry}
\usepackage{color,soul}

\begin{document}
\noindent\hl{Highlighting} text feels good.
You can draw attention of people to a \hl{word} or perhaps 
\hl{even a whole sentence that spans across multiple lines
in such a way that hyphenation etc. are not affected.}
\end{document}

渲染示例

我怀疑让 TeX 绘制出与换行符配合良好的实际随机波动高光还需要做很多工作。

答案3

如果我认为我可以调整我编写的代码测试某个段落是否有分页符?进行下划线和突出显示。此解决方案使用 TikZ 和zref标记(后者用于测试分页符)标记文本的开始和结束,并使用 tikz 在标记之间绘制线条。会考虑当前线宽,并在每个段落分隔处自动设置新标记。这样做的好处是正常的文本排版完全不受影响!我正在努力推广这一点(请参阅在每条(基线)线上放置 TikZ 坐标或 \zlabel使用 TikZ 安装背景和前景页面层) 并尽快以包的形式提供更好的 UI。

\documentclass[twoside,11pt]{book}

\usepackage{zref-abspage}
\usepackage{zref-user}
\usepackage{tikz}
\usepackage{atbegshi}
\usetikzlibrary{calc,decorations.pathmorphing}

\makeatletter
\newcommand{\currentsidemargin}{%
  \ifodd\zref@extract{textarea-\thetextarea}{abspage}%
    \oddsidemargin%
  \else%
    \evensidemargin%
  \fi%
}

\newcounter{textarea}
\newcommand{\settextarea}{%
   \stepcounter{textarea}%
   \zlabel{textarea-\thetextarea}%
   \begin{tikzpicture}[overlay,remember picture]
    % Helper nodes
    \path (current page.north west) ++(\hoffset, -\voffset)
        node[anchor=north west, shape=rectangle, inner sep=0, minimum width=\paperwidth, minimum height=\paperheight]
        (pagearea) {};
    \path (pagearea.north west) ++(1in+\currentsidemargin,-1in-\topmargin-\headheight-\headsep)
        node[anchor=north west, shape=rectangle, inner sep=0, minimum width=\textwidth, minimum height=\textheight]
        (textarea) {};
  \end{tikzpicture}%
}


\usepackage{lipsum}
\newcommand\xlipsum[1][]{{\let\par\relax\lipsum*[#1]}}

\tikzset{tikzul/.style={yshift=-.75\dp\strutbox}}

\newcounter{tikzul}%
\newcommand\tikzul[1][]{%
    \begingroup
    \global\tikzullinewidth\linewidth
    \def\tikzulsetting{[#1]}%
    \stepcounter{tikzul}%
    \settextarea
    \zlabel{tikzul-begin-\thetikzul}%
    \tikz[overlay,remember picture,tikzul] \coordinate (tikzul-\thetikzul) at (0,0);% Modified \tikzmark macro
    \ifnum\zref@extract{tikzul-begin-\thetikzul}{abspage}=\zref@extract{tikzul-end-\thetikzul}{abspage}
    \else
        \AtBeginShipoutNext{\tikzul@endpage{#1}}%
    \fi
    \bgroup
    \def\par{\ifhmode\unskip\fi\egroup\par\@ifnextchar\noindent{\noindent\tikzul[#1]}{\tikzul[#1]\bgroup}}%
    \aftergroup\endtikzul
    \let\@let@token=%
}

\newlength\tikzullinewidth

\def\tikzul@endpage#1{%
\setbox\AtBeginShipoutBox\hbox{%
\box\AtBeginShipoutBox
\hbox{%
\begin{tikzpicture}[overlay,remember picture,tikzul]
\draw[#1]
    let \p1 = (tikzul-\thetikzul), \p2 = ([xshift=\tikzullinewidth+\@totalleftmargin]textarea.south west) in
    \ifdim\dimexpr\y1-\y2<.5\baselineskip
        (\x1,\y1) -- (\x2,\y1)
    \else
        let \p3 = ([xshift=\@totalleftmargin]textarea.west) in
        (\x1,\y1) -- +(\tikzullinewidth-\x1+\x3,0)
        % (\x3,\y2) -- (\x2,\y2)
        (\x3,\y1)
       \myloop{\y1-\y2+.5\baselineskip}{%
           ++(0,-\baselineskip) -- +(\tikzullinewidth,0)
       }%
    \fi
;
\end{tikzpicture}%
}}%
}%

\def\endtikzul{%
    \zlabel{tikzul-end-\thetikzul}%
    \ifnum\zref@extract{tikzul-begin-\thetikzul}{abspage}=\zref@extract{tikzul-end-\thetikzul}{abspage}
    \begin{tikzpicture}[overlay,remember picture,tikzul]
        \expandafter\draw\tikzulsetting
            let \p1 = (tikzul-\thetikzul), \p2 = (0,0) in
            \ifdim\y1=\y2
                (\x1,\y1) -- (\x2,\y2)
            \else
                let \p3 = ([xshift=\@totalleftmargin]textarea.west), \p4 = ([xshift=-\rightmargin]textarea.east) in
                (\x1,\y1) -- +(\tikzullinewidth-\x1+\x3,0)
                (\x3,\y2) -- (\x2,\y2)
                (\x3,\y1)
                \myloop{\y1-\y2}{%
                    ++(0,-\baselineskip) -- +(\tikzullinewidth,0)
                }%
            \fi
        ;
    \end{tikzpicture}%
    \else
    \settextarea
    \begin{tikzpicture}[overlay,remember picture,tikzul]
        \expandafter\draw\tikzulsetting
            let \p1 = ([xshift=\@totalleftmargin,yshift=-.5\baselineskip]textarea.north west), \p2 = (0,0) in
            \ifdim\dimexpr\y1-\y2<.5\baselineskip
                (\x1,\y2) -- (\x2,\y2)
            \else
                let \p3 = ([xshift=\@totalleftmargin]textarea.west), \p4 = ([xshift=-\rightmargin]textarea.east) in
                (\x3,\y2) -- (\x2,\y2)
                (\x3,\y2)
                \myloop{\y1-\y2}{%
                    ++(0,+\baselineskip) -- +(\tikzullinewidth,0)
                }
            \fi
        ;
    \end{tikzpicture}%
    \fi
    \endgroup
}

\def\myloop#1#2#3{%
    #3%
    \ifdim\dimexpr#1>1.1\baselineskip
        #2%
        \expandafter\myloop\expandafter{\the\dimexpr#1-\baselineskip\relax}{#2}%
    \fi
}

\makeatother

\begin{document}

text text text text text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
text text \tikzul[red]{text text text text text text text text text
text text text text text text text text text text text
text text text text} text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text

{\tikzset{tikzul/.style={yshift=1ex}}

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida
mauris. 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. \tikzul[line width=1.5\ht\strutbox,semitransparent,yellow]{Aenean
faucibus. Morbi dolor nulla, malesuada eu, pulvinar at, mollis ac, nulla. Curabitur auctor semper nulla. Donec varius orci eget risus. Duis nibh mi, congue
eu, accumsan eleifend, sagittis quis, diam. Duis eget orci sit amet orci dignissim
rutrum.}
text text text text text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
test
}

\begin{quote}
text text text text text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
text text \tikzul[red]{text text text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
text text text text} text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
\end{quote}

{\tikzset{tikzul/.style={yshift=.5ex}}

\begin{quote}
text text text text text text text text text text text
text text text text text text text text text text text
\begin{quote}
text text text text text text text text text text text
text text \tikzul[green]{text text text text text text text text text
text text text text text text text text text text text
text text text text 
text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
text text text text} text text text text text text text
\end{quote}
text text text text text text text text text text text
text text text text text text text text text text text
\end{quote}

\large
new text text text text text text text text text text text
text text \tikzul[red]{first text text text text text text text text
teXt teXt teXt teXt teXt teXt teXt teXt teXt teXt teXt
teXt teXt teXt teXt teXt teXt teXt teXt teXt teXt teXt
teXt teXt teXt last} teXt teXt teXt teXt teXt teXt teXt
text text text text text text text text text text text
text text text text text text text text text text text

text text text text text text text text text text text
text text text text text text text text text text text
text text \tikzul[red]{text text text text text text text text text
text text\par\noindent text text text text text text text text text
text text text text} text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
}

\begin{itemize}
    \item \tikzul{test test test} test
    \item test \tikzul{test test test} test
    \item aa \tikzul{test test test} test
    \item b \tikzul{test test 
text text text text text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
        test} test
\end{itemize}

text text text text text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text
text text \tikzul[red]{text text text text text text text text text
text text

 text text text text text text text text text
text text text text} text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text

text text text text text text text text text text text
text text text text text text text text text text text
text text \tikzul[red]{text text text text text text text text text
text text

\noindent text text text text text text text text text
\par text text text text} text text text text text text text
text text text text text text text text text text text
text text text text text text text text text text text


\end{document}

在此处输入图片描述

答案4

好吧,这是一个老问题,但有些问题仍未解决,所以我在这里尝试一下。这是Antal Spector-Zabusky 的回答我尝试处理其中的一些问题,例如分页符和在背景中突出显示。

如上所述,起点是soul。但我们在这里专门使用它来设置tikmarks每个连字点的开始和结束。这样做只是为了获取坐标,此时不进行任何绘制。

绘制由 完成,基于之前制作tikz AtBeginShipout的全套。它实际上是 完成的,这意味着它是在文本“下方”绘制的。tikzmarksAtBeginShipoutUpperLeft

但是,为了能够在正确的页面中的正确位置绘制正确的内容,我们必须对 s 进行索引tikzmark。因此,它们以 的形式命名p<page number>.d<decoration number>.<hyphenation point number>。基于此索引,我们可以tikzmark按顺序扫描 s,逐个装饰,逐页扫描。每个“装饰”的每一行都单独处理,最后,我们在基线处获得每行开头和结尾的 (x,y) 坐标。第一行、最后一行、中间行和单行在绘制时分别处理,从而允许每种情况都有不同的形状(这里没有使用,但可能非常有用)。

实际使用是由宏完成的\textdecor[...]{Text},它可以采用可选参数,然后在绘图时将该参数附加到 TikZ 样式。

结果:

在此处输入图片描述

(分页符)

在此处输入图片描述

更近一点:

在此处输入图片描述

代码:

\documentclass[12pt,DIV=8]{scrartcl}
\usepackage{soulutf8}
\usepackage{atbegshi}
\usepackage{etoolbox}
\usepackage{tikz}
\usetikzlibrary{tikzmark,calc,decorations.pathmorphing}


\colorlet{tdcolor}{yellow!35}

\makeatletter

\newlength{\txtdec@depth}
\setlength{\txtdec@depth}{.5ex}
\newlength{\txtdec@height}
\setlength{\txtdec@height}{\f@size pt} % sensible default

\newcounter{txtdec@hyphmark}
\newcounter{txtdec@decormark}
\setcounter{txtdec@decormark}{1}
\newcounter{txtdec@hyphdraw}
\setcounter{txtdec@hyphdraw}{1}
\newcounter{txtdec@decordraw}
\setcounter{txtdec@decordraw}{1}

\newcounter{txtdec@thenextpage}

\newtoggle{txtdec@unfinisheddecor}
\newtoggle{txtdec@stayonpage}
\newtoggle{txtdec@stayondecor}
\newtoggle{txtdec@stayonline}

% from https://tex.stackexchange.com/a/33765/105447
\newcommand{\gettikzxy}[3]{%
  \tikz@scan@one@point\pgfutil@firstofone#1\relax
  \edef#2{\the\pgf@x}%
  \edef#3{\the\pgf@y}%
}

% the drawing macros

\tikzset{%
  defaultdecor/.style={%
    fill=tdcolor,
    decoration = {random steps, amplitude=1pt, segment length=10pt},
    outer sep = -15pt,
    inner sep = 0pt,
    decorate}%
}

\newcommand{\txtdec@draw@all}{%
  \tikzset{thisdecor/.style/.expanded=\csuse{decor@tikz@style@\thetxtdec@decordraw}}%
  \path[defaultdecor, thisdecor]
        ($(\Xbegin,\Ybegin)+(0,-\txtdec@depth)$) rectangle
        ($(\Xend,\Yend)+(0,\txtdec@height-\txtdec@depth)$) ;
}

\newcommand{\txtdec@draw@begin}{%
  \tikzset{thisdecor/.style/.expanded=\csuse{decor@tikz@style@\thetxtdec@decordraw}}%
  \path[defaultdecor, thisdecor]
        ($(\Xbegin,\Ybegin)+(0,-\txtdec@depth)$) rectangle
        ($(\Xlineend,\Ylineend)+(0,\txtdec@height-\txtdec@depth)$) ;
}

\newcommand{\txtdec@draw@middle}{%
  \tikzset{thisdecor/.style/.expanded=\csuse{decor@tikz@style@\thetxtdec@decordraw}}%
  \path[defaultdecor, thisdecor]
        ($(\Xlinebegin,\Ylinebegin)+(0,-\txtdec@depth)$) rectangle
        ($(\Xlineend,\Ylineend)+(0,\txtdec@height-\txtdec@depth)$) ;
}

\newcommand{\txtdec@draw@end}{%
  \tikzset{thisdecor/.style/.expanded=\csuse{decor@tikz@style@\thetxtdec@decordraw}}%
  \path[defaultdecor, thisdecor]
        ($(\Xlinebegin,\Ylinebegin)+(0,-\txtdec@depth)$) rectangle
        ($(\Xend,\Yend)+(0,\txtdec@height-\txtdec@depth)$) ;
}


% using soul to set tikzmarks

\def\SOUL@tdleaders{%
  \stepcounter{txtdec@hyphmark}%
  \tikzmark{p\thepage.d\arabic{txtdec@decormark}.\arabic{txtdec@hyphmark}}%
  \leaders\hrule\@depth\z@\@height\z@\relax
}

\def\SOUL@tdunderline#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@tdleaders\hskip\dimen@}%
      \hskip\dimen@
    }%
    \unhcopy\z@
  }}

\def\SOUL@tdpreamble{%
  \spaceskip\SOUL@spaceskip
  \setcounter{txtdec@hyphmark}{0}%
  \tikzmark{p\thepage.d\arabic{txtdec@decormark}.begin}%
}
\def\SOUL@tdeverysyllable{%
  \SOUL@tdunderline{%
    \the\SOUL@syllable
    \SOUL@setkern\SOUL@charkern
  }%
  \stepcounter{txtdec@hyphmark}%
  \tikzmark{p\thepage.d\arabic{txtdec@decormark}.\arabic{txtdec@hyphmark}}%
}
\def\SOUL@tdeveryhyphen{%
  \discretionary{%
    \unkern
    \SOUL@tdunderline{%
      \SOUL@setkern\SOUL@hyphkern
      \SOUL@sethyphenchar
    }%
    \stepcounter{txtdec@hyphmark}%
    \tikzmark{p\thepage.d\arabic{txtdec@decormark}.\arabic{txtdec@hyphmark}}%
  }{}{}%
}
\def\SOUL@tdeveryexhyphen#1{%
  \SOUL@setkern\SOUL@hyphkern
  \SOUL@tdunderline{#1}%
  \stepcounter{txtdec@hyphmark}%
  \tikzmark{p\thepage.d\arabic{txtdec@decormark}.\arabic{txtdec@hyphmark}}%
  \discretionary{}{}{%
    \SOUL@setkern\SOUL@charkern
  }%
}
\def\SOUL@tdpostamble{%
  % create an extra mark, vertically displaced, to create an exit condition for the last line
  \stepcounter{txtdec@hyphmark}%
  \raisebox{-5pt}{\tikzmark{p\thepage.d\arabic{txtdec@decormark}.\arabic{txtdec@hyphmark}}}%
  \tikzmark{p\thepage.d\arabic{txtdec@decormark}.end}%
  \stepcounter{txtdec@decormark}%
}
\def\SOUL@tdsetup{%
  \SOUL@setup
  \let\SOUL@preamble\SOUL@tdpreamble
  \let\SOUL@everysyllable\SOUL@tdeverysyllable
  \let\SOUL@everyhyphen\SOUL@tdeveryhyphen
  \let\SOUL@everyexhyphen\SOUL@tdeveryexhyphen
  \let\SOUL@postamble\SOUL@tdpostamble
}
\DeclareRobustCommand*\textdecor[1][]{%
  \csxdef{decor@tikz@style@\thetxtdec@decormark}{#1}%
  \csxdef{decor@fsize@\thetxtdec@decormark}{\f@size pt}%
  \SOUL@tdsetup\SOUL@}


% get the drawing done AtBeginShipout

\AtBeginShipout{%
  \AtBeginShipoutUpperLeft{%
    % getting the number of the next page
    \setcounter{txtdec@thenextpage}{\thepage}%
    \stepcounter{txtdec@thenextpage}%
    % if the current decoration occurs on this page, stay on it
    \iftikzmark{p\thepage.d\arabic{txtdec@decordraw}.\arabic{txtdec@hyphdraw}}{%
      \toggletrue{txtdec@stayonpage}}{}%
    \whileboolexpr{togl {txtdec@stayonpage}}{%
      \begin{tikzpicture}[remember picture, overlay]
        \setlength{\txtdec@height}{\csuse{decor@fsize@\thetxtdec@decordraw}}%
        \iftikzmark{p\thepage.d\arabic{txtdec@decordraw}.begin}{%
          % if current decor begins in current page, get coordinates
          \gettikzxy{(pic cs:p\thepage.d\arabic{txtdec@decordraw}.begin)}{\Xbegin}{\Ybegin}}{%
          % if current decor begins in previous page, set to top left of the page
          \gettikzxy{(current page.north west)}{\Xbegin}{\Ybegin}}%
        \iftikzmark{p\thepage.d\arabic{txtdec@decordraw}.end}{%
          % if current decor ends in current page, get coordinates
          \gettikzxy{(pic cs:p\thepage.d\arabic{txtdec@decordraw}.end)}{\Xend}{\Yend}}{%
          % if current decor ends in future page, set to bottom right of the page
          \gettikzxy{(current page.south east)}{\Xend}{\Yend}}%
        \ifdim\Ybegin=\Yend % the simplest case, a single line
          \txtdec@draw@all
          \stepcounter{txtdec@decordraw}%
        \else % current textdecor has a line break          
          \toggletrue{txtdec@stayondecor}%
          \whileboolexpr{togl {txtdec@stayondecor}}{%
            \gettikzxy{(pic cs:p\thepage.d\arabic{txtdec@decordraw}.\arabic{txtdec@hyphdraw})}{\Xlinebegin}{\Ylinebegin}%
            \edef\Xcurrent{\Xlinebegin}%
            \edef\Ycurrent{\Ylinebegin}%
            \edef\Xnext{\Xcurrent}%
            \edef\Ynext{\Ycurrent}%
            \toggletrue{txtdec@stayonline}%
            \whileboolexpr{togl {txtdec@stayonline}}{%
              \ifdim\Ycurrent=\Ynext
                \stepcounter{txtdec@hyphdraw}%
                % if the following tikzmark exists, we are at a page break
                \iftikzmark{p\arabic{txtdec@thenextpage}.d\arabic{txtdec@decordraw}.\arabic{txtdec@hyphdraw}}{%
                  \edef\Xcurrent{\Xnext}%
                  \edef\Ycurrent{\Ynext}%
                  \gettikzxy{(current page.south east)}{\Xnext}{\Ynext}
                  \togglefalse{txtdec@stayondecor}%
                }{% else, we remain on the same page
                  \iftikzmark{p\thepage.d\arabic{txtdec@decordraw}.\arabic{txtdec@hyphdraw}}{%
                    \edef\Xcurrent{\Xnext}%
                    \edef\Ycurrent{\Ynext}%
                    \gettikzxy{(pic cs:p\thepage.d\arabic{txtdec@decordraw}.\arabic{txtdec@hyphdraw})}{\Xnext}{\Ynext}}{}%
                }%
              \else
                \edef\Xlineend{\Xcurrent}%
                \edef\Ylineend{\Ycurrent}%
                % if we are on the first line of the current decoration
                \ifdim\Ylinebegin=\Ybegin
                  \txtdec@draw@begin
                \else
                  % if we are on the last line of the current decoration
                  \ifdim\Ycurrent=\Yend
                    \txtdec@draw@end
                    \stepcounter{txtdec@decordraw}%
                    \setcounter{txtdec@hyphdraw}{1}%
                    \togglefalse{txtdec@stayondecor}%
                  % if we are in a middle line of the decoration
                  \else
                    \txtdec@draw@middle
                  \fi
                \fi
                \togglefalse{txtdec@stayonline}%  
              \fi
            }%
          }%
        \fi
      \end{tikzpicture}%
      % if the beginning of the next decor does not exist in this page, leave this page
      \iftikzmark{p\thepage.d\arabic{txtdec@decordraw}.begin}{}{%
        \togglefalse{txtdec@stayonpage}}%
      % if the continuation of the current decor exists in the next page, leave this page
      \iftikzmark{p\arabic{txtdec@thenextpage}.d\arabic{txtdec@decordraw}.\arabic{txtdec@hyphdraw}}{%
        \togglefalse{txtdec@stayonpage}}{}% 
    }%
  }%
}

\makeatother

\begin{document}

\vspace*{5cm}

Lorem ipsum \textdecor{dolor sit amet, consectetuer adipiscing}
elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae,
felis. Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget,
consectetuer id, vulputate a, magna. \textdecor[draw=green]{Donec
  vehicula augue eu neque. Pellentesque habitant morbi tristi-que
  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. 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,
fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi auctor
lorem non justo. Nam lacus libero, pretium at, lobortis vitae,
ultricies et, tellus. 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.  Nam dui ligula,
fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi auctor
lorem non justo. Nam lacus libero, pretium at, lobortis vitae,
ultricies et, tellus. 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.  \textdecor[red,
draw=black]{Nam dui ligula, fringilla a, euismod sodales, sollicitudin
  vel, wisi. Morbi auctor lorem non justo. Nam lacus libero, pretium
  at, lobortis vitae, ultricies et, tellus. 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.  Nam dui ligula, fringilla a, euismod sodales, sollicitudin
  vel, wisi. Morbi auctor lorem non justo. Nam lacus libero, pretium
  at, lobortis vitae, ultricies et, tellus. 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. Pellentesque a nulla.} Cum sociis natoque
penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Aliquam tincidunt urna. Nulla ullamcorper vestibulum
turpis. Pellentesque cursus luctus mauris.

\begin{quotation}
  Lorem ipsum {\large \textdecor[blue]{dolor sit amet, consectetuer
      adipiscing}} elit. Ut purus elit, vestibulum ut, placerat ac,
  adipiscing vitae, felis. Curabitur dictum gravida mauris. Nam arcu
  libero, nonummy eget, consectetuer id, vulputate a, magna.
  \textdecor[green]{Donec vehicula augue eu neque. Pellentesque
    habitant morbi tristi-que 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.
\end{quotation}

\begin{itemize}
\item Lorem ipsum \textdecor[blue, draw=magenta]{dolor sit amet,
    consectetuer adipiscing} elit.
\item Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae,
  felis. Curabitur dictum gravida mauris. Nam arcu libero, nonummy
  eget, consectetuer id, vulputate a, magna. \textdecor[gray]{Donec
    vehicula augue eu neque. Pellentesque habitant morbi tristi-que
    senectus et netus et malesuada fames ac -- turpis ---
    egestas. Mauris ut leo.}
\end{itemize}

\end{document}

总体设置非常灵活,因为我们可以tikz在从中选择的一组坐标上进行绘制tikzmarks。分页符可以正常工作(包括多个)。如前所述,突出显示绘制在文本下方。装饰高度响应当前字体大小。

申请地址:

啊!很重要。这里也感谢@marmot,他给了我很多启发和想法在聊天中

相关内容