我尝试使用ulem包,发现在相邻的文本加上连续的下划直线或波浪线,会出现直线或波浪线粘连在一起的问题,而手动加上空格,虽然会避免粘连的问题,但是又改变了字距。有没有符合中文字距的下划线和波浪线的方案,要求连续的下划线不能粘连,需要断开。
\documentclass{article}
\usepackage[normalem]{ulem}
\usepackage{xeCJK}
\setlength{\ULdepth}{2.4pt}
\begin{document}
\noindent
史记 赵世家
\noindent
\uwave{史记}\uwave{赵世家}
\noindent
\uline{史记}\uline{赵世家}
\noindent
\uwave{史记} \uwave{赵世家}
\noindent
\uline{史记} \uline{赵世家}
\end{document}
我调教Gemini,使用tikz给相邻两段中文绘制下划线或波浪线,下划线/波浪线不粘连了,也没有错误的中文字距的问题,但是产生一些新的问题,问得Gemini无解:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing, calc}
\usepackage{xcolor}
\usepackage{xeCJK}
\begin{document}
% 测量各个文本部分的宽度
\newlength{\widthA}
\newlength{\widthB}
\newlength{\widthC}
\newlength{\widthD}
\settowidth{\widthA}{史}
\settowidth{\widthB}{管子君臣}
\settowidth{\widthC}{中庸}
\settowidth{\widthD}{及}
% 定义一个新命令,用于绘制整行并精确对齐
\newcommand{\myWaveLine}[4]{
\begin{tikzpicture}[baseline=(c.base)]
% 将所有文本放在一个节点中
\node (c) [inner sep=0pt, at={(0,0)}, anchor=west] {#1#2#3#4};
% 绘制第一段波浪线
\draw[decorate, decoration={snake, amplitude=0.5pt, segment length=1.5pt}, line width=0.3pt]
($(c.south west)+(\widthA,-2pt)$) -- ($(c.south west)+(\widthA+\widthB,-2pt)$);
% 绘制第二段波浪线
\draw[decorate, decoration={snake, amplitude=0.5pt, segment length=1.5pt}, line width=0.3pt]
($(c.south west)+(\widthA+\widthB,-2pt)$) -- ($(c.south west)+(\widthA+\widthB+\widthC,-2pt)$);
% 使用白色矩形创建间隙,并遮盖不完美的波形
\fill [white, opacity=1.0] ($(c.south west)+(\widthA-0.2pt, -10pt)$) rectangle ($(c.south west)+(\widthA+0.2pt, 10pt)$);
\fill [white, opacity=1.0] ($(c.south west)+(\widthA+\widthB-0.4pt, -10pt)$) rectangle ($(c.south west)+(\widthA+\widthB+0.4pt, 10pt)$);
\end{tikzpicture}
}
\noindent
管子君臣中庸
\noindent
史管子君臣中庸及
\noindent
\myWaveLine{史}{管子君臣}{中庸}{及}
% 移除 tikzpicture 引入的额外间距
\vspace{-5pt}
\noindent
史管子君臣中庸及
\end{document}
这段代码中,在使用noindent,绘制波浪线之后,无法左对齐;
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing, calc}
\usepackage{xcolor}
\usepackage{xeCJK}
\begin{document}
% 测量各个文本部分的宽度
\newlength{\widthA}
\newlength{\widthB}
\newlength{\widthC}
\newlength{\widthD}
\settowidth{\widthA}{史}
\settowidth{\widthB}{管子君臣}
\settowidth{\widthC}{中庸}
\settowidth{\widthD}{及}
% 定义一个新命令,用于绘制整行并精确对齐
\newcommand{\myWaveLine}[4]{
\begin{tikzpicture}[baseline=(c.base)]
% 将所有文本放在一个节点中
\node (c) [inner sep=0pt, at={(0,0)}, anchor=west] {#1#2#3#4};
% 绘制第一段直线
\draw[line width=0.3pt]
($(c.south west)+(\widthA,-2pt)$) -- ($(c.south west)+(\widthA+\widthB,-2pt)$);
% 绘制第二段直线
\draw[line width=0.3pt]
($(c.south west)+(\widthA+\widthB,-2pt)$) -- ($(c.south west)+(\widthA+\widthB+\widthC,-2pt)$);
% 使用白色矩形创建间隙,并遮盖不完美的直线
\fill [white, opacity=1.0] ($(c.south west)+(\widthA-0.2pt, -10pt)$) rectangle ($(c.south west)+(\widthA+0.2pt, 10pt)$);
\fill [white, opacity=1.0] ($(c.south west)+(\widthA+\widthB-0.4pt, -10pt)$) rectangle ($(c.south west)+(\widthA+\widthB+0.4pt, 10pt)$);
\end{tikzpicture}
}
\noindent
管子君臣中庸
\noindent
史管子君臣中庸及
\noindent
\myWaveLine{史}{管子君臣}{中庸}{及}
% 移除 tikzpicture 引入的额外间距
\vspace{-5pt}
\noindent
史管子君臣中庸及
\end{document}
这段代码中,在使用noindent,绘制下划线之后,无法左对齐。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing, calc, positioning}
\usepackage{xcolor}
\usepackage{xeCJK}
\begin{document}
% 您原始的、能够工作的波浪线宏
\def\mywaveunderline#1{%
\tikz[baseline=(node.south)]{
\node[inner sep=0pt](node){#1};
\draw[decorate, decoration={snake, amplitude=0.5pt, segment length=1.5pt}, line width=0.3pt, overlay, shorten >=0pt, shorten <=0pt] ($(node.south west)+(0pt,-2pt)$) -- ($(node.south east)+(0pt,-2pt)$);
}%
}
% 测量各个文本部分的宽度
\settowidth{\dimen0}{史}
\settowidth{\dimen1}{管子君臣}
\settowidth{\dimen2}{中庸}
\settowidth{\dimen3}{及}
% --- 最终的、可靠的排版方法 ---
\noindent
管子君臣中庸
\noindent
史管子君臣中庸及
\noindent
史管子君臣中庸及
\noindent
% 使用一个 TikZ 环境来精确排版第二行
\begin{tikzpicture}[baseline=(c.base)]
% 放置所有文字,但使用 \hphantom 确保它们不占空间,以便我们可以手动定位波浪线
\node[inner sep=0pt, anchor=west] (c) at (0,0) {\hphantom{史}\mywaveunderline{管子君臣}\mywaveunderline{中庸}\hphantom{及}};
% 绘制“史”和“及”两个字,并确保它们的对齐
\node[anchor=west, inner sep=0pt] at (c.west) {史};
\node[anchor=west, inner sep=0pt, right=0pt of c.east]{及};
\end{tikzpicture}
\noindent
史管子君臣中庸及
\end{document}
这段代码,尝试解决左对齐的问题,但是两段波浪线又连在一起,庸和及两字之间出现了不该有的空白,此后,就问得Gemini胡说了。有大佬基于此三段代码实现一个完美的解决方法吗?先在此谢谢了。
首先,在对「CJK文字」进行下划线时,建议使用xeCJKfntef
宏包来实现,否则会出现无法正确换行的情况。
xeCJKfntef
的功能\documentclass[fontset=fandol,12pt]{ctexart}
\usepackage{xeCJKfntef}
\setlength{\parindent}{0pt}
\begin{document}
\CJKunderline{史记赵世家}
\CJKunderline*{史记赵世家}
\CJKunderwave{史记赵世家}
\CJKunderwave*{史记赵世家}
\CJKunderline{史记,赵世家}
\CJKunderline*{史记,赵世家}
\CJKunderline-{史}%
\CJKunderline-{记}%
,%
\CJKunderline-{赵}%
\CJKunderline-{世}%
\CJKunderline-{家}%
\CJKunderwave{史记,赵世家}
\CJKunderwave*{史记,赵世家}
\CJKunderwave-{史}%
\CJKunderwave-{记}%
,%
\CJKunderwave-{赵}%
\CJKunderwave-{世}%
\CJKunderwave-{家}%
\end{document}
另外,这种「逐字」需要下划线和下划波浪线的实际用途是什么(?)一般波浪线和下划线很少需要逐字添加绘制(?)
最后,要想调好不借助现有功能是比较困难的:
每个CJK字符最终呈现的宽度是并不统一的,我在xeCJkfntef
的框架下做了如下修改,也有瑕疵...
\documentclass[fontset=fandol,12pt]{ctexart}
\usepackage{xeCJKfntef}
\usepackage{zhlipsum}
\setlength{\parindent}{0pt}
\ExplSyntaxOn
%Line 5716~5733
% \NewDocumentCommand \CJKunderline { s t- s o }
% {
% \xeCJK_ulem_group_begin:
% \xeCJK_fntef_boot:nnNNNn { underline } { uline } #1#2#3 {#4}
% \xeCJK_fntef_initial:nnn
% { \l__xeCJK_uline_depth_tl }
% { \l__xeCJK_uline_sep_tl }
% {
% \l__xeCJK_uline_format_tl
% \tex_vrule:D
% height \dim_eval:n { \l__xeCJK_uline_thickness_tl }
% depth \c_zero_dim
% width .2em
% }
% \xeCJK_ulem_on:n
% }
\RenewDocumentCommand \CJKunderline { s t- s o }
{
\xeCJK_ulem_group_begin:
\xeCJK_fntef_boot:nnNNNn { underline } { uline } #1#2#3 {#4}
\xeCJK_fntef_initial:nnn{ \l__xeCJK_uline_depth_tl }{ \l__xeCJK_uline_sep_tl }{%
\l__xeCJK_uline_format_tl
\tex_vrule:D height \dim_eval:n { \l__xeCJK_uline_thickness_tl } depth \c_zero_dim width .95em\hskip1pt}%
\xeCJK_ulem_on:n
}
\ExplSyntaxOff
\xeCJKsetup{ underwave = { symbol = \sixly \hskip1pt plus 1fill minus 1fill\char 58\hskip0pt plus 1fill minus 1fill\char 58\hskip1pt plus 1fill minus 1fill\relax } }
\begin{document}
\CJKunderline{史记赵世家}
\CJKunderline*{史记赵世家}
\CJKunderwave{史记赵世家}
\CJKunderwave*{史记赵世家}
\CJKunderline{史记,赵世家}
\CJKunderline*{史记,赵世家}
\CJKunderwave{史记,赵世家}
\CJKunderwave*{史记,赵世家}
\end{document}
这里的刚性宽度控制在字更多的时候很容易「歪」,同时如果遇到压缩的标点符号/换行等特殊情况,也是难以正常工作的....
测试了一下xeCJKfntef包的使用,能用,但是画线的位置不够准确。
\documentclass{article}
\parindent=0pt
\usepackage{xeCJK}
\usepackage{xeCJKfntef}
\begin{document}
天地玄黄宇宙洪荒日月盈昃辰宿列张史记赵世家寒来暑往秋收冬藏闰余成岁律吕调阳云腾致雨露结为霜金生丽水玉出昆冈
\medskip
天地玄黄宇宙洪荒日月盈昃辰宿列张\CJKunderwave-{史记}\CJKunderwave-{赵世家}寒来暑往秋收冬藏闰余成岁律吕调阳云腾致雨露结为霜金生丽水玉出昆冈
\medskip
天地玄黄宇宙洪荒日月盈昃辰宿列张\CJKunderline-{史记}\CJKunderline-{赵世家}寒来暑往秋收冬藏闰余成岁律吕调阳云腾致雨露结为霜金生丽水玉出昆冈
\medskip
天地玄黄宇宙洪荒日月盈昃辰宿列张\CJKunderdot{史记}\CJKunderline-{\CJKunderdot{赵世家}}寒来暑往秋收冬藏闰余成岁律吕调阳云腾致雨露结为霜金生丽水玉出昆冈
\medskip
张\CJKunderwave-{史记}\CJKunderwave-{赵世家}寒
\medskip
张\CJKunderline-{史记}\CJKunderline-{赵世家}寒
\medskip
张\CJKunderdot{史记}\CJKunderline-{\CJKunderdot{赵世家}}寒
\end{document}
@U156235 请为这三段代码添加三个效果图示。
另外,如果你需要批量设置
\noindent
你可以使用
或者
还有,不太建议在对解决方法不太了解的情况下vibe coding,这样得到的代码并不稳健,自己对tex的理解也并没有加深。
@u70550 效果图已添加
@u70550 求助于AI,是不得已而为之