带圆角的文本框突出显示(基于灵魂)

带圆角的文本框突出显示(基于灵魂)

这里这是 Gonzalo Medina 提供的出色解决方案。有人能帮我制作出漂亮的小圆角吗?

答案1

这是解决这个问题的另一种方法(因此也是另一种答案)。它是回答 LaTeX 中酷炫文本突出显示的问题

这种方法的优点是允许分页,并且角半径的设置也更加灵活。但也有一些限制,尤其是装饰的设置是全局进行的(完整讨论在上述答案中)。

结果是:

在此处输入图片描述

代码如下:

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


\colorlet{tdcolor}{gray!50}

\newlength{\LineWidth}
\setlength{\LineWidth}{0.7pt}

\newlength{\CornerRadius}
\setlength{\CornerRadius}{5pt}

\newlength{\BorderDispl}
\setlength{\BorderDispl}{2pt}

\makeatletter

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

\newcounter{txtdec@hyphmark}
\newcounter{txtdec@decormark}
\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

\newcommand{\txtdec@draw@all}{%
  \draw[tdcolor, line width=\LineWidth, rounded corners=\CornerRadius] ($(\Xbegin,\Ybegin)+(-\BorderDispl,-\txtdec@depth)$) rectangle ($(\Xend,\Yend)+(\BorderDispl,\txtdec@height-\txtdec@depth)$) ;
}

\newcommand{\txtdec@draw@begin}{%
  \draw[tdcolor, line width=\LineWidth, rounded corners=\CornerRadius]
    ($(\Xlineend,\Ylineend)+(0,\txtdec@height-\txtdec@depth)$) --
    ($(\Xbegin,\Ybegin)+(-\BorderDispl,\txtdec@height-\txtdec@depth)$) --
    ($(\Xbegin,\Ybegin)+(-\BorderDispl,-\txtdec@depth)$) --
    ($(\Xlineend,\Ylineend)+(0,-\txtdec@depth)$) ;
}

\newcommand{\txtdec@draw@middle}{%
  \draw[tdcolor, line width=\LineWidth] ($(\Xlinebegin,\Ylinebegin)+(0,-\txtdec@depth)$) -- ($(\Xlineend,\Ylineend)+(0,-\txtdec@depth)$) ;
  \draw[tdcolor, line width=\LineWidth] ($(\Xlinebegin,\Ylinebegin)+(0,\txtdec@height-\txtdec@depth)$) -- ($(\Xlineend,\Ylineend)+(0,\txtdec@height-\txtdec@depth)$) ;
}

\newcommand{\txtdec@draw@end}{%
  \draw[tdcolor, line width=\LineWidth, rounded corners=\CornerRadius]
  ($(\Xlinebegin,\Ylinebegin)+(0,\txtdec@height-\txtdec@depth)$) --
  ($(\Xend,\Yend)+(\BorderDispl,\txtdec@height-\txtdec@depth)$) --
  ($(\Xend,\Yend)+(\BorderDispl,-\txtdec@depth)$) --
  ($(\Xlinebegin,\Ylinebegin)+(0,-\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
  \stepcounter{txtdec@decormark}%
  \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}%
}
\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{\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}{\f@size pt}%
        \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{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{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 \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{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{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{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}

答案2

我也在寻找一种基于 soul-tikz 方法来实现此目的的方法,并且可以根据您链接的答案取得一些成果。

其原始结构是 Antal Spector-Zabusky 的(https://tex.stackexchange.com/a/6029/105447),但我从 Gonzalo Medina 的变奏开始(https://tex.stackexchange.com/a/52336/105447)。

代码中有很多内容超出了我的理解范围,但我从一个简单的想法开始,并可以调整其中的相关部分。这个想法是将“框”的开始和结束处的垂直线稍微移位,以便能够为其添加角。这种移位本身是受欢迎的,因为如果这些垂直线离第一个/最后一个字符不太近,视觉效果会更好。但这也是必要的(据我所知),因为在我看来,为了达到同样的目的而缩短水平线似乎很困难。

关于评论中上面提到的 的重要性soul,重点是,据我所知, 它soul用于定义绘图的基本坐标,但绘图本身是由 TikZ 执行的。换句话说,Antal Spector-Zabusky 的想法中的绘图部分不是基于soul\hl宏。没错,一路上,每个连字符点都设置了坐标,因此确实很难篡改顶部和底部的线条。

结果如下:

在此处输入图片描述

或者更接近:

在此处输入图片描述

用于生成它的代码是:

\documentclass{article}
\usepackage{soul}
\usepackage{tikz}
\usetikzlibrary{calc}


\newlength\LineWidth
\setlength\LineWidth{0.7pt}

\newlength\CornerRadius
\setlength\CornerRadius{2pt}

\newlength\baseliney
\setlength\baseliney{-1.5pt}

\newlength\heighty
  \makeatletter
    \setlength{\heighty}{\f@size pt}
  \makeatother

\colorlet{HLcolor}{black}

\makeatletter

\newcommand\highlight@DoHighlight{%
    \draw[HLcolor,line width=\LineWidth,opacity=.3]  ($(begin highlight)+(0,\baseliney)$) -- ($(end highlight)+(0,\baseliney)$) ;
    \draw[HLcolor,line width=\LineWidth,opacity=.3]  ($(begin highlight)+(0,\baseliney+\heighty)$) -- ($(end highlight)+(0,\baseliney+\heighty)$) ;
}

\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*\circ[1][]{%
    \tikzset{this highlighter/.style={#1}}%
    \SOUL@setup
    %
    \def\SOUL@preamble{%
        \begin{tikzpicture}[overlay, remember picture]
        \highlight@BeginHighlight
        \draw[HLcolor,line width=\LineWidth,opacity=.3]  ($(begin highlight)+(-\CornerRadius,\baseliney+\CornerRadius)$) -- ($(begin highlight)+(-\CornerRadius,\baseliney+\heighty-\CornerRadius)$) ;
        \draw[HLcolor,line width=\LineWidth,opacity=.3] ($(begin highlight)+(0,\baseliney+\heighty)$) arc [radius=\CornerRadius, start angle=90, end angle=180];
        \draw[HLcolor,line width=\LineWidth,opacity=.3] ($(begin highlight)+(0-\CornerRadius,\baseliney+\CornerRadius)$) arc [radius=\CornerRadius, start angle=180, end angle=270];
        \highlight@EndHighlight
        \end{tikzpicture}%
    }%
    %
    \def\SOUL@postamble{%
        \begin{tikzpicture}[overlay, remember picture]
        \highlight@EndHighlight
        \highlight@DoHighlight
        \draw[HLcolor,line width=\LineWidth,opacity=.3]  ($(end highlight)+(\CornerRadius,\baseliney+\CornerRadius)$) -- ($(end highlight)+(\CornerRadius,\baseliney+\heighty-\CornerRadius)$) ;
        \draw[HLcolor,line width=\LineWidth,opacity=.3] ($(end highlight)+(\CornerRadius,\baseliney+\heighty-\CornerRadius)$) arc [radius=\CornerRadius, start angle=0, end angle=90];
        \draw[HLcolor,line width=\LineWidth,opacity=.3] ($(end highlight)+(0,\baseliney)$) arc [radius=\CornerRadius, start angle=270, end angle=360];
        \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 dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
    vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida
    mauris. \circ{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. Cur-
    abitur auctor semper nulla. \circ{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. Cras nec ante. Pellentesque a nulla. \circ{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}

该解决方案的局限性在于它限制了角的半径,因为它还决定了垂直线的位移,如果将半径设置得太大,线条就会侵入周围的单词。

我也放弃了与填充相关的一切,但我想这里应用的相同原则可以扩展到包括它。

我还调整了代码,使其能够灵活地记录字体大小,并在开始时全局定义主要定位设置。

相关内容