正如今天的另一个问题wrapfig
,我正在尝试寻找一种比标准解决方案(如或手动使用)更灵活的方式来让文本环绕图形\parshape
,我目前专注于实验性的 expl3 包xgalley
。
其中一个问题是如何将图形放在文本的右侧。我的第一次尝试(如下所示)使用了不太纯粹的普通 TeX 命令和 expl3 的混合。是否有一种更“正确”和“纯粹”的、最好是基于 expl3 的方法来将图形放在右边?
当前构造还存在一些问题,包括它使用了\vadjust
,这可能会扰乱 的机制xgalley
。另外,我无法使 的内容\putright
顶部对齐(\vtop
搞乱了一切),因此 的第一个参数\putright
(降低数字的行数)必须高于传递给 的参数\cutright
。
\documentclass{article}
\usepackage{lipsum,xgalley,graphicx}
\ExplSyntaxOn
\cs_new_eq:NN \cutright \galley_cutout_right:nn
\ExplSyntaxOff
\newcommand\putright[2]{% #1 = number of lines to lower the figure, #2 = content
\leavevmode
\vadjust{%
\hfill
\smash{%
\lower\dimexpr#1\baselineskip-2.5\lineskip\relax\llap{#2}%
}%
}\ignorespaces
}
\begin{document}
\cutright{4}{.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth}
\putright{12}{\includegraphics[width=.3\textwidth]{duck}}
\lipsum
\end{document}
答案1
如果您确实想要问题中显示的语法,请参阅下面我的原始答案。
\cutright
这次编辑修改了用户界面,消除了之前使用的需要\putright
。这个版本还产生了更整洁的结果,我认为,比我第一次尝试的错误更少。
新版本定义仅有的以下命令:
\putright[<options>]{<content for cut-out>}
\putleft[<options>]{<content for cut-out>}
\resetindents
\xwrapfigsetup{<options>}
<options>
是使用键值接口定义的。\xwrapfigsetup{}
只知道一个键,该键本身采用使用和cutout
创建的切口的默认选项列表。并且知道更多键:\putright
\putleft
\putright
\putleft
hmargin=<dimension>
指定切口内容左侧和右侧的总水平空间(默认为 2ex);
skip lines=<integer>
指定除了适合内容所需的行数之外还允许剪切的行数(默认值为 1);
top lines=<integer>
指定剪切之前段落顶部保留的未改变的行数(默认为 2)。
其余部分都将自动处理或根本不处理,但有一个相当大的例外,即在剪切排版后恢复标准段落形状。
\putright
/\putleft
计算适当的缩进行数和缩进所需的宽度。然后他们将剪切部分添加到当前段落,最后排版剪切部分的内容。
这意味着简单地说
\putright{\includegraphics[width=.3\textwidth]{duck}}
\lipsum
生产
相似地,
\putleft[top lines=3]{\includegraphics[width=.3\textwidth]{duck}}
\kant[3]
跳过的额外线为鸭子的头部和尾部留出了一点空间。显然,如果您喜欢更紧或更松的配合,可以修改这一点。
完整代码(早期版本我的答案在这里:
\documentclass{article}
\usepackage{kantlipsum,xgalley,tikz}
\ExplSyntaxOn
\box_new:N \l_xwrapfig_fig_box
\box_new:N \l_xwrapfig_vfig_box
\box_new:N \l_xwrapfig_hfig_box
\dim_new:N \l_xwrapfig_wd_dim
\dim_new:N \l_xwrapfig_totalht_dim
\clist_new:N \l_xwrapfig_indents_clist
\int_new:N \l_xwrapfig_lines_int
\int_new:N \l_xwrapfig_totallines_int
\fp_new:N \l_xwrapfig_adjfig_fp
\keys_define:nn { xwrapfig }
{
cutout .code:n = {
\keys_set:nn { xwrapfig / cutout } { #1 }
}
}
\keys_define:nn { xwrapfig / cutout }
{
hmargin .dim_set:N = \l_xwrapfig_adjwd_dim,
hmargin .initial:n = { 2ex },
skip~lines .int_set:N = \l_xwrapfig_adjlines_int,
skip~lines .initial:n = { 1 },
top~lines .int_set:N = \l_xwrapfig_toplines_int,
top~lines .initial:n = { 2 },
}
\cs_generate_variant:Nn \galley_cutout_right:nn { nV }
\cs_generate_variant:Nn \galley_cutout_left:nn { nV }
\cs_new_protected:Nn \xwrapfig_prewrap:n
{
\clist_clear:N \l_xwrapfig_indents_clist
\clist_clear:N \l_xwrapfig_zindents_clist
\vbox_set:Nn \l_xwrapfig_vfig_box { #1 }
\dim_set:Nn \l_xwrapfig_totalht_dim { \box_ht:N \l_xwrapfig_vfig_box + \box_dp:N \l_xwrapfig_vfig_box }
\hbox_set:Nn \l_xwrapfig_hfig_box { #1 }
\dim_set:Nn \l_xwrapfig_wd_dim { \box_wd:N \l_xwrapfig_hfig_box + \l_xwrapfig_adjwd_dim }
\int_set:Nn \l_xwrapfig_totallines_int { ( \l_xwrapfig_totalht_dim / \baselineskip ) + \l_xwrapfig_adjlines_int }
\int_zero:N \l_xwrapfig_lines_int
\int_do_while:nn { \l_xwrapfig_lines_int < \l_xwrapfig_totallines_int }
{
\int_incr:N \l_xwrapfig_lines_int
\clist_put_right:Nn \l_xwrapfig_indents_clist { \l_xwrapfig_wd_dim }
}
}
\cs_new_protected:Nn \xwrapfig_postwrap:
{
\box_set_ht:Nn \l_xwrapfig_fig_box { 0pt }
\box_set_dp:Nn \l_xwrapfig_fig_box { 0pt }
\skip_vertical:n { -\baselineskip }
\box_use:N \l_xwrapfig_fig_box
}
\cs_new_protected:Nn \xwrapfig_putright:nn
{
\xwrapfig_prewrap:n { #2 }
\galley_cutout_right:nV { #1 } \l_xwrapfig_indents_clist
\vbox_set:Nn \l_xwrapfig_fig_box
{
\fp_set:Nn \l_xwrapfig_adjfig_fp { ( #1 + .5\l_xwrapfig_adjlines_int ) * \baselineskip }
\skip_vertical:n { \fp_to_dim:N \l_xwrapfig_adjfig_fp }
\hbox_to_wd:nn { \linewidth } { \skip_horizontal:n { \linewidth - \l_xwrapfig_wd_dim + .5\l_xwrapfig_adjwd_dim } #2 }
}
\xwrapfig_postwrap:
}
\cs_new_protected:Nn \xwrapfig_putleft:nn
{
\xwrapfig_prewrap:n { #2 }
\galley_cutout_left:nV { #1 } \l_xwrapfig_indents_clist
\vbox_set:Nn \l_xwrapfig_fig_box
{
\fp_set:Nn \l_xwrapfig_adjfig_fp { ( #1 + .5\l_xwrapfig_adjlines_int ) * \baselineskip }
\skip_vertical:n { \fp_to_dim:N \l_xwrapfig_adjfig_fp }
\hbox_to_wd:nn { \l_xwrapfig_wd_dim } { \skip_horizontal:n { .5\l_xwrapfig_adjwd_dim } #2 }
}
\xwrapfig_postwrap:
}
\cs_generate_variant:Nn \xwrapfig_putleft:nn { Vn }
\cs_generate_variant:Nn \xwrapfig_putright:nn { Vn }
\NewDocumentCommand\putright { O { } +m }
{
\keys_set:nn { xwrapfig / cutout } { #1 }
\xwrapfig_putright:Vn \l_xwrapfig_toplines_int { #2 }
}
\NewDocumentCommand\putleft { O { } +m }
{
\keys_set:nn { xwrapfig / cutout } { #1 }
\xwrapfig_putleft:Vn \l_xwrapfig_toplines_int { #2 }
}
\NewDocumentCommand\resetindents { }
{
\galley_parshape_set_multi:nnnN { 0 } { 0pt } { 0pt } \c_true_bool
}
\NewDocumentCommand\xwrapfigsetup { m }
{
\keys_set:nn { xwrapfig } { #1 }
}
\ExplSyntaxOff
\begin{document}
\kant[1]
\putright[top lines=0]{%
\begin{tikzpicture}
\newcommand*\len{1.5}
\draw [thick] (0,0,\len) coordinate (a) \foreach \i/\j in {(\len,0,\len)/b,(\len,0,0)/c,(\len,\len,0)/g,(0,\len,0)/h,(0,\len,\len)/e,(\len,\len,\len)/f} {-- \i coordinate (\j)} -- (g) (f) -- (b) (a) -- (e);
\coordinate (d) at (0,0,0);
\draw [gray] (a) -- (d) edge (c) -- (h);
\foreach \i/\j in {a/left,b/right,c/right,d/left,e/left,f/right,g/above,h/above} \node at (\i) [\j] {\i};
\end{tikzpicture}}
Let $G S_8$ and $X = \{\{a,g\},\{b,h\},\{c,e\},\{d,f\}\}$
\kant[1-2]
\kant[3]
\clearpage
\putright[top lines=0]{%
\begin{tikzpicture}
\newcommand*\len{1.5}
\draw [thick] (0,0,\len) coordinate (a) \foreach \i/\j in {(\len,0,\len)/b,(\len,0,0)/c,(\len,\len,0)/g,(0,\len,0)/h,(0,\len,\len)/e,(\len,\len,\len)/f} {-- \i coordinate (\j)} -- (g) (f) -- (b) (a) -- (e);
\coordinate (d) at (0,0,0);
\draw [gray] (a) -- (d) edge (c) -- (h);
\foreach \i/\j in {a/left,b/right,c/right,d/left,e/left,f/right,g/above,h/above} \node at (\i) [\j] {\i};
\end{tikzpicture}}
Let $G S_8$ and $X = \{\{a,g\},\{b,h\},\{c,e\},\{d,f\}\}$
\kant[1-2]
\putleft[top lines=3]{\includegraphics[width=.3\textwidth]{duck}}
\kant[3]
\clearpage
\putleft[top lines=0]{%
\begin{tikzpicture}
\newcommand*\len{1.5}
\draw [thick] (0,0,\len) coordinate (a) \foreach \i/\j in {(\len,0,\len)/b,(\len,0,0)/c,(\len,\len,0)/g,(0,\len,0)/h,(0,\len,\len)/e,(\len,\len,\len)/f} {-- \i coordinate (\j)} -- (g) (f) -- (b) (a) -- (e);
\coordinate (d) at (0,0,0);
\draw [gray] (a) -- (d) edge (c) -- (h);
\foreach \i/\j in {a/left,b/right,c/right,d/left,e/left,f/right,g/above,h/above} \node at (\i) [\j] {\i};
\end{tikzpicture}}
Let $G S_8$ and $X = \{\{a,g\},\{b,h\},\{c,e\},\{d,f\}\}$\par
\kant[4]
\putright{\includegraphics[width=.3\textwidth]{duck}}
\kant[5]
\resetindents
\xwrapfigsetup{%
cutout={%
skip lines=3,
hmargin=5ex,
top lines=1,
}
}
\kant[6]
\kant[7]
\putright{\includegraphics[width=.3\textwidth]{duck}}
\kant[5]
\end{document}
请注意,我不清楚如何将其仅应用于当前文本块。它的工作方式非常奇怪。我尝试使用,\galley_parshape_set_single:nVVN
但只能让它正常工作\putleft
。
\resetindents
因此,提供用于重置段落缩进。这需要在\putleft
或之后\putright
使用。
我不明白的是,为什么第二段\kant[1-2]
不受影响,而后面的一段\kant[3]
却受影响(如wipet 指出) 或者为什么左侧剪切空间在最后一次使用后几个段落中重复出现。
我怀疑关于如何做到这一点存在一些根本性的问题,但我现在还不明白。
原始答案
你想要这样的东西吗?
\documentclass{article}
\usepackage{lipsum,xgalley,graphicx}
\ExplSyntaxOn
% don't use \cs_new_eq for document-level macros (which necessarily fail to conform to expl3 syntax) - use xparse
\NewDocumentCommand\cutright { m m }
{
\galley_cutout_right:nn { #1 } { #2 }
}
\coffin_new:N \l_gaussler_fig_coffin
\box_new:N \l_gaussler_fig_box
\NewDocumentCommand\putright { m m }
{
\vbox_set:Nn \l_tmpa_box { #2 }
\dim_set:Nn \l_tmpa_dim { \box_dp:N \l_tmpa_box + \box_ht:N \l_tmpa_box }
\int_set:Nn \l_tmpa_int { ( #1 - ( \l_tmpa_dim / \baselineskip ) ) /2 }
\skip_vertical:n { #1\baselineskip - \l_tmpa_dim +\l_tmpa_int\baselineskip }
\skip_horizontal:N \linewidth
\vbox_to_zero:n
{
\hbox_overlap_left:n { #2 }
}
\skip_vertical:n { -#1\baselineskip + \l_tmpa_dim - \l_tmpa_int\baselineskip }
}
\ExplSyntaxOff
\begin{document}
\cutright{4}{.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth}
\putright{9}{\includegraphics[width=.3\textwidth]{duck}}
\lipsum
\end{document}
答案2
我不明白两件事。当基于 TeX 基元的解决方案更简单、更直接时,为什么需要显式 expl3 解决方案。为什么在\cutright
和中使用不同的数据\putright
。第一个参数 (4) 表示未触及的行数,但第二个参数 (12)——我不知道它是什么。
我可以帮你做第二件事。定义:
\def\putright#1#2{\vskip\parskip
\hbox to\hsize{\hss
\vbox to0pt{\kern#1\baselineskip\kern-.8\baselineskip \hbox{#2}\vss}}
\nobreak\vskip-\parskip\vskip-\baselineskip
}
然后您可以对两者使用相同的数据:\cutright{4}{...}\putright{4}{...}
。